How to code "Jump" button that always detects (beginner-level)

Ok, so this is my beginner-level code to have my character jump as long as they are resting on a GameObject tagged as “platform”:

public Rigidbody2D rbody;
public float moveForce = 10;
private bool touchingPlatform = false;
   

    void FixedUpdate () {
   
        float movements = Input.GetAxis ("Horizontal");
        Vector2 moveHorizontalVector = new Vector2(movements*moveForce, 0);
rbody.AddForce(moveHorizontalVector);

        if ( Input.GetButtonDown ("Jump") && touchingPlatform == true) {
            rbody.AddForce (new Vector2 (0, 30* moveForce));
            touchingPlatform = false;
        }
    }


    void OnCollisionEnter2D(Collision2D other) {
        Debug.Log ("Colliding with an object tagged as: " + other.gameObject.tag);

        if (other.gameObject.CompareTag ("platform")) {
            touchingPlatform = true;
        }
    }
   

    void OnCollisionExit2D(Collision2D other) {
Debug.Log ("Now leaving an object tagged as: " + other.gameObject.tag);
       
if (other.gameObject.CompareTag ("platform")) {
            touchingPlatform = false;
        }
    }

The issue is that this only detects the jump key being pressed about 80-90% of the time. A fair amount of times I press the “Jump” button, nothing happens. I was toying with the idea of having a boolean-type “jumping” variable in the Update method and using an if/else GetButton (continuous) instead of GetButtonDown (single-touch).

Here is what I tried - but for some reason, now it won’t jump at all, even though using the Debug.Log I can see that the “jumping” boolean is true. If I replace the “jumping” part of the if-conditional with GetButtonDown(“Jump”) then it works, but again only about 80-90% of the time.

Help?

Is there some forever keyListener method that would sense the GetButtonDown 100% of the time?

public Rigidbody2D rbody;
    public float moveForce = 10;
    private bool touchingPlatform = false;
    private bool jumping = false;


    void Start () {
    }

    void Update () {
        if (Input.GetButton ("Jump")) {
            bool jumping = true;
        } else {
            bool jumping = false;
        }
    }


    void FixedUpdate () {

        float movements = Input.GetAxis ("Horizontal");
        Vector2 moveHorizontalVector = new Vector2(movements*moveForce, 0);
        rbody.AddForce(moveHorizontalVector);


        if ( jumping && touchingPlatform == true) {
            rbody.AddForce (new Vector2 (0, 30* moveForce));
            touchingPlatform = false;
            jumping = false;
        }

    }

    void OnCollisionEnter2D(Collision2D other){
        if(other.gameObject.CompareTag("platform")){
            touchingPlatform = true;
        }
    }

    void OnCollisionExit2D(Collision2D other){
        if(other.gameObject.CompareTag("platform")){
            touchingPlatform = false;
        }
    }

}

You definitely want to get all your inputs in Update. Only use FixedUpdate for physics operations.

Store the result of GetButtonDown in “jumping” in Update, and don’t set it false until you actually apply the jump force in FixedUpdate.

Thank you. What’s what I figured. However, my code up above won’t work with the boolean-type “jumping” as a condition. It will work with the “GetButtonDown(“Jump”)” but not with the “jumping”. Can anyone help me as to why?

I just can’t seem to get the FixedUpdate if conditional to trigger when setting the bolean in Update …

You defined bools called “jumping” in Update that don’t exist outside it, and you don’t do anything with them, so they have no effect.

–Eric

Eric,

I thought since I defined the “private bool jumping = false;” at the very top of the class as a member variable. Shouldn’t I be able to edit it in both Update and FixedUpdate then?

Thank you,
Brendan

That is correct, but you’re also defining two new local variables in Update by beginning them with “bool”. That signifies a new variable declaration for that scope only.

OOOOOOOOOH, thank you! The little typos.