Okay so I’ve encountered a problem when trying to prevent a player from sticking to a block when a collision is detected when moving horizontally. I’ve gone through this code over and over and cannot find where the problem is. There’s two C# scripts involved. If anybody has the time and can take a look I’d appreciate it so much. The problem seems like it would either be in the PlayerPhysics section that checks for the left and right collisions or in the first portion of the update in the PlayerController. The first is
PlayerPhysics
[RequireComponent (typeof(BoxCollider))]
public class PlayerPhysics : MonoBehaviour {
public LayerMask collisionMask;
//will allow us to define what objects we want the object/player to collide with
new private BoxCollider collider; //creates BoxCollider named collider, which is assigned in the void Start() function
private Vector3 s; //initializes Vector3 for size
private Vector3 c; //initializes Vector3 for center position
private float skin = .005f; //used to keep object slightly off the ground so it will actually detect the ground
[HideInInspector] //Hides next line in inspector
public bool grounded; //creates bool function for grounded
[HideInInspector]
public bool movementStopped;
Ray ray; //creates Ray named ray (Ray is an infinite line starting at origin and going in some direction)
RaycastHit hit; //RaycastHit is a structure used to get information back from the Ray
void Start(){
collider = GetComponent<BoxCollider>(); //Gets BoxCollider from object script is assigned to (which is the player)
s = collider.size; //gets collider size and assigns it to s
c = collider.center; //gets collider center and assigns it to c
}
public void Move(Vector2 moveAmount){ //Move Function
float deltaY = moveAmount.y;
float deltaX = moveAmount.x;
Vector2 p = transform.position;
//check collisions both above and below
grounded = false;
for(int i = 0; i < 3; i++){
float dir = Mathf.Sign (deltaY);
float x = (p.x + c.x - s.x/2) + s.x/2 * i; //left, center, and then rightmost point of collider
float y = p.y + c.y + s.y/2 * dir; //bottom of the collider
ray = new Ray(new Vector2(x, y), new Vector2(0, dir));
Debug.DrawRay(ray.origin, ray.direction); //Draws Ray to make sure it's working properly for debugging
if(Physics.Raycast(ray, out hit, Mathf.Abs(deltaY) + skin, collisionMask)){
//get distance between the player and the ground
float dst = Vector3.Distance(ray.origin, hit.point);
//stop players downward movement after coming within skin distance of collider
if(dst > skin){
deltaY = dst * dir - skin * dir;
}
else{
deltaY = 0;
}
grounded = true;
break;
}
}
//check collisions both left and right
movementStopped = false; //movement stopped is a bool function that will help prevent feeling 'stuck' when you hit a wall
for(int i = 0; i < 3; i++){
float dir = Mathf.Sign (deltaY);
float x = p.x + c.x + s.x/2 * dir; //left, center, and then rightmost point of collider
float y = p.y + c.y - s.y/2 + s.y/2 * i; //bottom of the collider
ray = new Ray(new Vector2(x, y), new Vector2(dir, 0));
Debug.DrawRay(ray.origin, ray.direction); //Draws Ray to make sure it's working properly for debugging
if(Physics.Raycast(ray, out hit, Mathf.Abs(deltaX) + skin, collisionMask)){
//get distance between the player and the ground
float dst = Vector3.Distance(ray.origin, hit.point);
//stop players downward movement after coming within skin distance of collider
if(dst > skin){
deltaX = dst * dir - skin * dir;
}
else{
deltaX = 0;
}
movementStopped = true;
break;
}
}
Vector2 finalTransform = new Vector2(deltaX, deltaY);
transform.Translate(finalTransform);
}
}
And the second is the PlayerController itself, which references PlayerPhysics:
void Update () {
if (playerPhysics.movementStopped){
targetSpeed = 0;
currentSpeed = 0;
}
targetSpeed = Input.GetAxisRaw ("Horizontal") * speed;
currentSpeed = IncrementTowards(currentSpeed, targetSpeed, acceleration);
//gets currentSpeed from IncrementTowards function
if(playerPhysics.grounded){ //if player is on the ground
//jump
amountToMove.y = 0; //sets amountToMove.y to zero so gravity doesn't keep building up
if(Input.GetButtonDown ("Jump")){ //Jump automatically assigned to spacebar
amountToMove.y = jumpHeight; //if player presses jump, amountToMove.y is set to the jumpHeight
}
}
amountToMove.x = currentSpeed;
amountToMove.y -= gravity * Time.deltaTime; //amountToMove.y subtracts gravity * Time.deltaTime
playerPhysics.Move(amountToMove * Time.deltaTime);
//sends amount to move * Time.deltaTimeto PlayerPhysics.cs's Move function
}
private float IncrementTowards(float n, float target, float a) {
if(n == target){
return n; //says that if currentSpeed equals targetSpeed, then currentSpeed will remain the same
}
else{
float dir = Mathf.Sign(target - n); //must n be increased or decreased to get to the target. Returns 1 or -1
n += a * Time.deltaTime * dir; //currentSpeed += acceleration * Time.deltaTime * direction
return (dir == Mathf.Sign(target - n))? n: target;
// if n has now passed target speed then return target speed, else return n (current speed)
}
}
}