My playercontroller script keeps bugging (C#)

Hi guys,

I wrote a player controller script which worked fine with the player but every now and then there are bugs. There is no errors with the scripts its just the player sometimes jumping i press jump and the player wont jump.

Any help would be greatly appreciated

CODE

using UnityEngine;
using System.Collections;

public class PlayerController : MonoBehaviour {

	//Movement
	public float speed;
	public float jump;
	float moveVelocity;
	
	//Grounded Vars
	bool grounded = true;
	
	void Update ()
	{
		//Jumping
		if (Input.GetKeyDown (KeyCode.Space) || Input.GetKeyDown (KeyCode.UpArrow) || Input.GetKeyDown (KeyCode.Z) || Input.GetKeyDown (KeyCode.W))
		{
			if(grounded)
			{
				GetComponent<Rigidbody2D> ().velocity = new Vector2 (GetComponent<Rigidbody2D> ().velocity.x, jump);
			}
		}
		
		moveVelocity = 0;
		
		//Left Right Movement
		if (Input.GetKey (KeyCode.LeftArrow) || Input.GetKey (KeyCode.A))
		{
			moveVelocity = -speed;
		}
		if (Input.GetKey (KeyCode.RightArrow) || Input.GetKey (KeyCode.D))
		{
			moveVelocity = speed;
		}
		
		GetComponent<Rigidbody2D> ().velocity = new Vector2 (moveVelocity, GetComponent<Rigidbody2D> ().velocity.y);
		
	}
	//Check if Grounded
	void OnCollisionEnter2D ()
	{
		grounded = true;
	}
	void OnCollisionExit2D ()
	{
		grounded = false;
	}
}

It’s a bit hard to know what’s going wrong without seeing the scene but looking at the code I see a possible problem you might be having. For example if you are walking and then happen to touch a wall, and then get away from it the code

 void OnCollisionExit2D ()
 {
     grounded = false;
 }

will make the grounded go false without leaving the ground (you just stopped touching the wall). One workaround you can do is create a layer for the ground (or a tag would just do the trick too if you find it easier) and then check the collision enter and exit with that layer:

    void OnCollisionEnter2D(Collision2D coll) {
        if (coll.gameObject.layer == LayerMask.NameToLayer("Ground"))
          grounded = true;

        
    }

    void OnCollisionExit2D(Collision2D coll) {
        if (coll.gameObject.layer == LayerMask.NameToLayer("Ground"))
         grounded = false;

        
    }

You can change your inspector to debug mode and view the ‘grounded’ field in real time. As with others I suspect that it’s being set false when you don’t expect it to be - if you collide with two objects and then stop colliding with one you could end up with grounded = false while you are still touching the ground.

Using a tag for the ground could help, but so too could adding a count on each oncollisionenter and subtracting with each exit and allowing a jump if contacts > 0