Search Unity

Double Jump broken

Discussion in 'Scripting' started by EddieChen580418, Apr 19, 2021.

  1. EddieChen580418

    EddieChen580418

    Joined:
    Mar 14, 2021
    Posts:
    3
    There is an error with my script when performing a double jump. When performing the second jump, it will register it does the first jump (again) and the second jump which results in a total of 3 jumps instead of 2. This results occurs when I implement a coyote timer and the isGrounded check.

    *This is groundCheck.cs*
    Code (CSharp):
    1.  private void OnCollisionEnter2D(Collision2D collision)
    2.     {
    3.         Debug.Log("On collison enter");
    4.  
    5.         if (collision.collider.tag == "platform")
    6.         {
    7.             Player.GetComponent<movement>().isGrounded = true;
    8.          
    9.             animator.SetBool("IsJumping", false);
    10.             Debug.Log(Time.frameCount +  "This is hitting" + collision.collider.gameObject.name);
    11.  
    12.  
    13.         }
    14.     }
    15.  
    16.  
    17.     private void OnCollisionExit2D(Collision2D collision)
    18.     {
    19.  
    20.         Debug.Log("On collison exit");
    21.  
    22.         if (collision.collider.tag == "platform")
    23.         {
    24.          
    25.             Player.GetComponent<movement>().isGrounded = false;
    26.         }
    27.     }

    *This is movement.cs*

    Code (CSharp):
    1.    // jump and double jump
    2.         if (Input.GetButtonDown("Jump") && hangCounter > 0f && isHanging == false && doneFirstJump == false) // //ForceMode2D.Impulse = instand force rather than gradual speed
    3.                                                                                                          // current issue is that it registers the first jump twice
    4.         {
    5.             rb.AddForce(new Vector2(0, JumpHeight), ForceMode2D.Impulse);
    6.             inAir = true;
    7.             animator.SetBool("IsJumping", true);
    8.             isHanging = true;
    9.             doneFirstJump = true;
    10.             Debug.Log(Time.frameCount + "IS IT GROUNDED?: (FIRST JUMP)" + isGrounded);
    11.  
    12.             Debug.Log(Time.frameCount + "this is single jump");
    13.         }
    14.  
    15.  
    16.  
    17.         if (Input.GetButtonDown("Jump") && isGrounded == false && inAir == true)
    18.         {
    19.             rb.AddForce(new Vector2(0, extraJumpHeight), ForceMode2D.Impulse); //ForceMode2D.Impulse = instand force rather than gradual speed
    20.             inAir = false;
    21.             Debug.Log("this is the double jump");
    22.             Debug.Log(Time.frameCount + "IS IT GROUNDED?: (SECOND JUMP)" + isGrounded);
    23.  
    24.         }
    The following code results in this results:


    http://prntscr.com/11o9xj6


    Right after the first (single jump), the isGrounded boolean is checked to true for 4 frames (this should be false) before the onCollisionExit is executed which makes isGrounded false.

    The 4 frame is what results in the single jump being executed with the second jump.

    I have also made sure there are no other colliders the ground collider can hit when in the air. I am not sure what causes this problem and how to fix it. Any help you be greatly appreciated!
     

    Attached Files:

  2. EddieChen580418

    EddieChen580418

    Joined:
    Mar 14, 2021
    Posts:
    3

    Attached Files:

  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,739
    Input.GetButtonDown() is not to be used anywhere except in Update(). See the docs for why, but it basically boils down to this timing diagram:

    https://docs.unity3d.com/Manual/ExecutionOrder.html

    That also shows you when the collider callbacks get called.

    Similarly, anything to do with physics (rigidbodies) should ONLY be done in FixedUpdate().

    Generally gather all input from Input.GetButtonDown(); and store it to temporary boolean values. This is broadly called "collecting input."

    Then in other functions such as in FixedUpdate() or your collider callbacks, act upon those temporary boolean values and clear them back to false, effectively "consuming" the previously-collected input.
     
    EddieChen580418 and Joe-Censored like this.
  4. EddieChen580418

    EddieChen580418

    Joined:
    Mar 14, 2021
    Posts:
    3

    Thanks so much! this fixed my issue, i've changed the input key detection to be Update() and then in FixedUpdate(), I do the physics and jump stuff
     
    Kurt-Dekker likes this.