Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Bool not changing despite being told to

Discussion in 'Scripting' started by thegamer539, Sep 10, 2020.

  1. thegamer539

    thegamer539

    Joined:
    Apr 5, 2018
    Posts:
    10
    So I'm making a jump script and I want the player to only jump if space is pressed and he bool is set to false.
    So I created this script:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Groundcheck : MonoBehaviour
    6. {
    7.     public bool IsJumping = false;
    8.  
    9.     public Rigidbody Player;
    10.  
    11.  
    12.  
    13.     private void Update()
    14.     {
    15.         if (Input.GetButtonDown("Jump") && !IsJumping)
    16.         {
    17.             Player.AddForce(new Vector3(0, 10, 0 * Time.deltaTime), ForceMode.Impulse);
    18.             IsJumping = true;
    19.         }
    20.     }
    21.  
    22.     private void OnCollisionEnter(Collision other)
    23.     {
    24.         if (other.gameObject.CompareTag("Floor"))
    25.         {
    26.             IsJumping = false;
    27.         }
    28.     }
    29.  
    30. }
    31.  

    However the 'IsJumping' bool won't change even though its colliding with an object that has the tag 'Floor'.
    The player only jumps once.

    Can anyone help.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,762
    I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - are you meeting all the requirements to get OnCollisionEnter called? (see docs)
    - is this code even running? which parts are running? how often does it run?
    - if OnCollisionEnter is being called, what is the tag?
    - what are the values of the variables involved? Are they initialized?

    Knowing this information will help you reason about the behavior you are seeing.
     
    Joe-Censored likes this.
  3. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    Not directly related to your problem but this looks suspect:
    0 * Time.deltaTime

    0 times anything is always 0. I suspect you meant to multiply the whole Vector3 by that amount. However I would advise just removing the Time.deltaTime operation completely. Impulse force is meant to be applied only once, not over a period of time, so it doesn't really make sense to factor in deltaTime.
     
  4. thegamer539

    thegamer539

    Joined:
    Apr 5, 2018
    Posts:
    10
    The reason why I added the deltaTime operation is because at times the force applied would sometimes be really huge or really small. I suspected its because I didn't add a deltaTime operation however I don't think thats the case since it didn't do anything.
     
  5. thegamer539

    thegamer539

    Joined:
    Apr 5, 2018
    Posts:
    10
    Thank you I figured it out. I used Debug.Log and discovered that I wasn't meeting the requirements for OnCollisionEnter.
    My GroundCheck object needed a Rigidbody. However I discovered an easier way to handle jumping and it works although I'm not sure if it will always be efficient. I done this instead:

    private void FixedUpdate()
    {
    if (rb.velocity.y == 0)
    {
    if (Input.GetKeyDown(KeyCode.Space))
    {
    rb.AddForce(new Vector3(0, 10 * Time.fixedDeltaTime, 0), ForceMode.Impulse);
    }
    }
    }
     
  6. thegamer539

    thegamer539

    Joined:
    Apr 5, 2018
    Posts:
    10

    Thank you I figured it out. I used Debug.Log and discovered that I wasn't meeting the requirements for OnCollisionEnter.
    My GroundCheck object needed a Rigidbody. However I discovered an easier way to handle jumping and it works although I'm not sure if it will always be efficient. I done this instead:

    private void FixedUpdate()
    {
    if (rb.velocity.y == 0)
    {
    if (Input.GetKeyDown(KeyCode.Space))
    {
    rb.AddForce(new Vector3(0, 10 * Time.fixedDeltaTime, 0), ForceMode.Impulse);
    }
    }
    }
     
  7. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,722
    Careful with this code. Efficiency is not a problem at all, but what is a problem is calling Input.GetKeyDown inside FixedUpdate.

    FixedUpdate doesn't run every frame. Often the game is running at 100FPS or higher, and FixedUpdate is only running 50 times per second. What this means is that there are many frames in which FixedUpdate doesn't run at all. Input data in Unity is updated once per frame. Input.GetKeyDown in particular is only true for the single frame in which the key is first pressed. There's also a possibility that, during a framerate hiccup, FixedUpdate actually runs TWICE or more in a single frame.

    Therefore, given your current code, the following possibilities are likely to happen while playing your game:
    • FixedUpdate will not run during the frame when the key is first pressed, and you will miss the input entirely, leading to the player pressing the jump button and no jump happening.
    • FixedUpdate will run multiple times during the single frame when the key is pressed, and you will add the force multiple times, resulting in a higher jump than usual
    Thankfully this problem is pretty easy to fix. The general idea is to make an instance variable that keeps track of the player's intent to jump inside Update(), where input processing is reliable. Then in FixedUpdate(), you consume that intent and perform the jump. Something like this:

    Code (CSharp):
    1. bool jumpRequested = false;
    2.  
    3. void Update() {
    4.   if (Input.GetKeyDown(KeyCode.Space)) {
    5.     jumpRequested = true;
    6.   }
    7. }
    8.  
    9. void FixedUpdate() {
    10.   if (jumpRequested) {
    11.     jumpRequested = false;
    12.     rb.AddForce(...);
    13.   }
    14. }
    Final note: be careful with checking velocity to determine if the player is on the ground. The velocity of the character might also reach zero at the height of their jump, allowing a second jump at the peak with perfect timing; although given floating point precision, it is highly unlikely.
     
    Kurt-Dekker likes this.
  8. thegamer539

    thegamer539

    Joined:
    Apr 5, 2018
    Posts:
    10
    Thanks I think thats why, sometimes, the player jumps way higher than usual.