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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Dubugging a jumping issue

Discussion in 'Scripting' started by jeffreyjene, Dec 26, 2019.

  1. jeffreyjene

    jeffreyjene

    Joined:
    Jul 9, 2018
    Posts:
    14
    I have a piece of code that causes a character to jump in place. That's all it does. It looks like this:

    Code (CSharp):
    1.    void LateUpdate()
    2.     {
    3.         velocity = Vector3.zero;
    4.        
    5.         if (!IsGrounded())
    6.         {
    7.             momentum -= transform.up * gravity * Time.deltaTime;
    8.         }
    9.  
    10.         else
    11.         {
    12.             momentum = Vector3.zero;
    13.            
    14.             if (Input.GetKeyDown(jumpKey))
    15.             {
    16.                 momentum += transform.up * jumpSpeed;
    17.                
    18.             }
    19.            
    20.         }
    21.        
    22.         velocity += momentum;
    23.         rb.velocity = velocity;
    24.     }
    It seems to work ok, but for some reason not 100% of the time. The button might need to be pressed once or several times to get the character to jump. I have:

    • Disabled the gravity on the rigidbody (rb) and froze the rotation. All other settings are default
    • The gravity is 9 and the jumpSpeed is 7
    • I've switched buttons/keys in case there was an input issue
    • I've verified that the controller is indeed grounded

    I need a second pair of eyes here. Why is this not working 100% of the time?
     
  2. All_American

    All_American

    Joined:
    Oct 14, 2011
    Posts:
    1,528
    Does it work 100% of the time in Update?
     
  3. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,256
    Update and LateUpdate work on the same loop so there should be no difference in function. FixedUpdate would cause intermittent input.

    I suspect this has to do with how IsGrounded() is working, its the only part I can see being a problem as I don't know what its doing.

    @jeffreyjene Can you post the code for IsGrouded()? I'm sure the problem is in there somewhere.
     
  4. Dextozz

    Dextozz

    Joined:
    Apr 8, 2018
    Posts:
    488
    Hmmm, I could be wrong, but try printing out your rb.velocity.

    momentum -= transform.up * gravity * Time.deltaTime;

    Will decrease your momentum more and more the longer your character is in the air. It will always be negative on the Y-axis because of that reason.

    velocity += momentum;

    Will lower your velocity by your momentum ALWAYS. Thus, I believe, that when the character hits the ground, the velocity on the Y-axis is still negative due to it never resetting.

    If I'm correct, once you Debug.Log(rb.velocity) you should see a negative number on your Y-axis. To fix it, simply set the Y velocity of the rb to 0 once the player is grounded:
    Code (CSharp):
    1. else
    2. {
    3.     momentum = Vector3.zero;
    4.     rb.velocity = new Vector3(rb.velocity.x, 0, rb.velocity.z);
    5.  
    6.     if (Input.GetKeyDown(jumpKey))
    7.     {
    8.         momentum += transform.up * jumpSpeed;
    9.     }
    10. }
     
  5. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,256
    This would cause you to have to push the jump button faster to "over take" the downward force, so it might be the issue as well. If you let this sit for awhile you probably couldn't press jump fast enough to even make it jump at all, and if it gets a fast enough downward force than it would start to push through the ground.

    Let us know if this is the issue.

    I would use built in gravity and then use rigidBody.AddForce() to jump myself to avoid such issues.
     
  6. adi7b9

    adi7b9

    Joined:
    Feb 22, 2015
    Posts:
    181
    Maybe because after you press jumpKey your rb still IsGrounded().
    Move your rb.velocity = velocity; line to Update()
     
  7. jeffreyjene

    jeffreyjene

    Joined:
    Jul 9, 2018
    Posts:
    14
    Here is the IsGrounded code:

    Code (CSharp):
    1. public bool IsGrounded()
    2.     {
    3.         RaycastHit hit;
    4.         origin = collider.bounds.center;
    5.         sensorDistance = collider.bounds.extents.y - sensorRadius + sensorOffset;
    6.        
    7.         if (Physics.SphereCast(origin, sensorRadius, direction, out hit, sensorDistance, layerMask, QueryTriggerInteraction.UseGlobal))
    8.         {
    9.             grounded = true;
    10.             currentHitDistance = hit.distance;
    11.         }
    12.         else
    13.         {
    14.             currentHitDistance = sensorDistance;
    15.             grounded = false;
    16.         }
    17.  
    18.         return grounded;
    19.     }
    sensor radius is .3, collider is 2 units by .5, layermask is everything, and the offset is .01f to get it just a smidge above the ground. The controller is pretty much sitting on the spherecast.
     
  8. jeffreyjene

    jeffreyjene

    Joined:
    Jul 9, 2018
    Posts:
    14

    Thanks, that isn't the issue. I also want precise control over the character. I'm overriding the rb's velocity during movement, so any AddForce would be zeroed out or overwritten.
     
  9. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,256
    SphereCast for something like this is over kill, its more processing than OverlapSphere when the overlap will do the same thing. Use SphereCast like a RayCast that needs to be wider than a Ray.

    Should use layermasks to stop it from registering on other colliders. I usually setup a Ground layer and have it only look for collisions with that.

    Other than that I have no idea what could be wrong. Debug.Log IsGrounded to make sure its registering the ground. Debug.Log everything really each step of the way to see what goes on, or use the debugger in VS and step through the code and have a look.

    Code (CSharp):
    1. Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
    2. bool grounded = IsGrounded();
    3.  
    4. if (grounded && Input.GetButtonDown("Jump"))
    5. {
    6.       rBody.AddForce(Vector3.up * jumpForce);
    7. }
    8.  
    9. rBody.velocity = new Vector3(move.x, rBody.velocity.y, move.z);
    You can use this technique in both 2D and 3D.