Jumping issue - poss linecast problem?

Hi Everyone,
Im playing around with a simple 2d platformer.
Ive created a player who can walk around and jump whilst using the animation component to add some simple animations based on his state, walking, jumping etc.

I found my code to be working fine, player walks jumps. animations all play when they should.
Ive run into an odd issue though when i added a second, higher platform, for the player to jump to.

The player will jump, the jump animation will play but when the player lands on the second platform he gets stuck in the jump animation, as if it hasnt detected the ground.
The player will only return to ā€˜no jumping’ mode when he is moved back to the original lower platform her jumped from.

Same happens if i start the player off on the higher platform, he can jump and move fine until he lands on the lower platform where suddenly hes stuck in jump mode.

Anyone have any ideas? I was thinking maybe it was something to do with the linecasting looking for the original Y coordinates in world space.?
Both platforms are on the Ground layer also.

Any help would be great, please ask if you need me to clarify anything.

public class PlayerCont : MonoBehaviour {

   float h ;
   Rigidbody2D  rb2d;
   bool facingRight = true;
   float speed = 5;  
   float jumpPower = 300f;
   Animator anim;
   bool jumping = false;
   private Transform groundCheck;
   bool grounded = false;

   // Use this for initialization
   void Start () {
  
     rb2d = GetComponent<Rigidbody2D>();
     anim = GetComponent<Animator> ();
     groundCheck = transform.Find ("groundCheck");
   }

   void Update()
   {
     //print (groundCheck.position);

     grounded = Physics2D.Linecast(transform.position,groundCheck.position ,1 << LayerMask.NameToLayer("Ground"));
     //print (groundCheck.position);
   }
  
   // Update is called once per frame
   void FixedUpdate () {

      h = Input.GetAxisRaw ("Horizontal");
     //print (h);

     //Move player

     //Moving right
     if (h == 1) {
       float movespeedR = 1 * speed;
       rb2d.velocity = new Vector2 (movespeedR ,rb2d.velocity.y ) ;
       anim.SetBool("Walks",true);
     }


     //Moving left
     if (h == -1) {
       float movespeedL = -1 * speed;
       rb2d.velocity = new Vector2(movespeedL ,rb2d.velocity.y);
       anim.SetBool ("Walks", true);
     }


     //Stopped moving
     if (h == 0 && jumping == false) {
       rb2d.velocity = new Vector2 (0, 0);
         anim.SetBool ("Walks", false);
     }

     //Player Jump
     if (Input.GetKeyDown(KeyCode.Space) && jumping == false)
     {   jumping = true;
       rb2d.AddForce (Vector2.up * jumpPower);
       anim.SetBool ("Jump", true);  
     }
     if (jumping == true && grounded == true) {
       jumping = false;
       anim.SetBool ("Jump", false);
     }
      

   }



}

You’re raycasting from the the player position to the ā€˜groundCheck’ position - it would make more sense to just raycast straight downwards from the player position or you’ll end up with weird results.

For example, in the attached pic you can see that the raycast would return ā€˜grounded’ for the player on the left but ā€˜not grounded’ for the one on the right (assuming the groundCheck transform is where the red marker is)

If you raycast straight down then both players would be marked as grounded. An easy way to do that would be to create an end point before the Linecast function.

e.g.

Vector3 endPos = transform.position;

// Move y position of player position 5 units downward on the Y axis (you might want to modify this to the right scale)
endPos.y -= 5.0f;
grounded = Physics2D.Linecast(transform.position,endPos,1 << LayerMask.NameToLayer("Ground"));

1 Like

I’ve also found that casting from transform.position can give inaccurate results when there is any slight overlap with the ground collider.

I prefer to ray cast from a higher position and use the distance to the hit point of impact to determine if I’m grounded or not.

for example using RayCast:

ray casting from origin of ā€œtransform.position + transform.upā€ in direction ā€œ-Vector3.upā€ will give you the hit point.

Calculate the distance with Vector3.Distance(origin, hit.point) and subtract the amount that you raised the start of the RayCast by (1 in the above example). This is will give you an accurate value on the players position relative to the ground which might be < 0 if the bottom of the collider is overlapping with the geometry.

Somebody smarter on these forums can probably tell you for certain but I’m not convinced about the accuracy of the cast when it originates within the collider you are testing against.

1 Like

I agree with @JoeMcDowall - it’s best to make your cast longer than necessary as it’s doubtful it’ll always hit the ground if the length doesn’t have any overlap