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

Question [SOLVED] : Explicit match on x and y velocities of a rigid body and jump function

Discussion in 'Scripting' started by rishikul030788, Aug 15, 2023.

  1. rishikul030788

    rishikul030788

    Joined:
    Jun 14, 2023
    Posts:
    10
    hello group,

    I need help to understand the difference between two approaches to execute a jump function in a 2D game-
    and why the first approach fails to execute

    Approach 1- Check input button pressed, get x and y velocities of the rigid body.
    Observation 1- Jump fails to execute while the rigid body is in motion on the x axis
    Code1 below -
    Code (CSharp):
    1.        if (Input.GetButtonDown("Jump") && rb.velocity.y == 0f && rb.velocity.x !=0f)
    2.         {
    3.             Debug.Log("jump while running");
    4.             Debug.Log("while running:" + rb.velocity.x);
    5.             if (IsGrounded() == true)
    6.             {
    7.                 //Debug.Log("value of isgrounded after jump is " + IsGrounded());
    8.                 //rb.velocity = new Vector2(0, 12f);
    9.                
    10.                 doublejump = true;
    11.                 jumpsoundeffect_audiosource.Play();
    12.                 rb.velocity = new Vector2(directionX*rb.velocity.x, jumpforce);
    13.             }

    Approach 2- Check input button pressed, do not perform any additional checks
    Observation 2 - Jump executes with rigid body is in motion on the x axis
    Code2 below -
    Code (CSharp):
    1. if (Input.GetButtonDown("Jump"))
    2.         {
    3.             Debug.Log("jump while running");
    4.             Debug.Log("while running:" + rb.velocity.x);
    5.             if (IsGrounded() == true)
    6.             {
    7.                 //Debug.Log("value of isgrounded after jump is " + IsGrounded());
    8.                 //rb.velocity = new Vector2(0, 12f);
    9.                
    10.                 doublejump = true;
    11.                 jumpsoundeffect_audiosource.Play();
    12.                 rb.velocity = new Vector2(directionX*rb.velocity.x, jumpforce);
    13.             }
    Explicit conditional match on x and y velocities of a rigid body leads to non-execution of jump func
     
  2. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    This is obviously because rb.velocity.y == 0f is not true. It could be 0.000001 or -0.0002
    Try replacing it with
    Math.Abs(rb.velocity.y) < 1E-4f
    just to see if that's the case.
     
    rishikul030788 and Yoreki like this.
  3. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,588
    Never do direct comparisons between floats and a specific number. These are very unlikely to return true.
    Always check for approximations, as suggested by @orionsyndrome. That's also why Approximately exists to automatically check if the values are within Epsilon of each other, which is simply a predefined small value.

    Generally speaking, why does velocity.x matter when jumping? Why check velocity.y, if the ground check fulfills the same purpose? Seems unnecessary.
     
    rishikul030788 likes this.
  4. rishikul030788

    rishikul030788

    Joined:
    Jun 14, 2023
    Posts:
    10
    so unlike a guaranteed true or false, this tells me that there is a transient state of motion when jump is pressed.
     
  5. rishikul030788

    rishikul030788

    Joined:
    Jun 14, 2023
    Posts:
    10
    you are correct, there is no need of redundant checks in production code. but today, you both made me realize that unity system works for approximations.
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
    You use it in a condition check.

    Ergo:
    Code (CSharp):
    1. bool noYMovement = Math.Abs(rb.velocity.y) < 1E-4f;
    The point is you just shouldn't check floating point numbers for equality.

    It's a general programming thing and not at all specific to Unity.
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Just so you realize that's an extremely small amount... 0.0001 to be exact.

    This means it is possible to be going UP faster than this and in a single frame be going DOWN faster than this if gravity is "strong enough," in which case it will not trip.

    Back-of-envelope checks tell me that earth's gravity at -9.8 m/s^2 at even 120fps (which is high!) is WAY strong enough to miss this tiny micro window, like nearly three orders of magnitude too large. You will be extremely unlikely to ever detect y velocity less than that tiny amount unless you just get lucky.

    Screen Shot 2023-08-15 at 9.25.29 PM.png

    Instead, every frame, compare if its sign changed in the direction you wanted compared to the previous frame.

    Floating (float) point imprecision:

    Never test floating point (float) quantities for equality / inequality. Here's why:

    https://starmanta.gitbooks.io/unitytipsredux/content/floating-point.html

    https://forum.unity.com/threads/debug-log-2000-0f-000-1f-is-200.1153397/#post-7399994

    https://forum.unity.com/threads/why-doesnt-this-code-work.1120498/#post-7208431

    "Think of [floating point] as JPEG of numbers." - orionsyndrome on the Unity3D Forums
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,769
    I just copied orion's coe so I wasn't paying too much attention to the actual value. It was the principle I was trying to bring across.
     
    Kurt-Dekker likes this.