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

Resolved How to make deterministic jump? Different jump height by different target frame rate.

Discussion in 'Scripting' started by fataldevelop, Jun 7, 2023.

  1. fataldevelop

    fataldevelop

    Joined:
    Jul 5, 2014
    Posts:
    17
    There is a simple formula to calculate initial velocity from given jump height:
    Code (CSharp):
    1. initialVelocity = Mathf.Sqrt(-2.0f * gravity * jumpHeight);
    But the reached jump height is different across different target frame rates.
    By Application.targetFrameRate = -1 ball reaches the jumpHeight almost perfectly. By targetFrameRate = 30 there is a small gap. I don't get it why it happens, i thought that using deltaTime should be enough.

    Project files attached.

    here is the code
    Code (CSharp):
    1.  
    2. public float jumpHeight;
    3.  
    4.     float gravity = -9.81f;
    5.     private float initialVelocity;
    6.     private float velocity;
    7.  
    8.     private void jump()
    9.     {
    10.         initialVelocity = Mathf.Sqrt(-2.0f * gravity * jumpHeight);
    11.         velocity = initialVelocity;
    12.     }
    13.  
    14.     private void Update()
    15.     {
    16.         if (Input.GetMouseButtonDown(0))
    17.         {
    18.             transform.position = Vector3.zero;
    19.             jump();
    20.         }
    21.  
    22.         if (velocity > 0)
    23.         {
    24.             // Apply gravity to the velocity
    25.             velocity += gravity * Time.deltaTime;
    26.  
    27.             // Move the ball based on the current velocity
    28.             transform.Translate(Vector3.up * velocity * Time.deltaTime);
    29.         }
    30.  
    31.     }
     

    Attached Files:

  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    It's a discrete simulation of a continuous phenomena. Putting it in Update() almost guarantees varying timesteps.

    Perhaps your needs would be better suited via FixedUpdate() ? You haven't said your needs.

    Two good discussions on Update() vs FixedUpdate() timing:

    https://jacksondunstan.com/articles/4824

    https://johnaustin.io/articles/2019/fix-your-unity-timestep

    Here is some timing diagram help:

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

    Here is an abbreviated and better-annotated version of the above:

    https://forum.unity.com/threads/a-c...ution-order-of-unity-event-functions.1381647/
     
  3. Neto_Kokku

    Neto_Kokku

    Joined:
    Feb 15, 2018
    Posts:
    1,750
    While it won't be 100% deterministic due to floating point precision limitations, you can greatly reduce effect of framerate on you jump if you use the correct formula for calculating how much to move the player every frame.

    Code (CSharp):
    1. public float jumpHeight;
    2.     float gravity = -9.81f;
    3.     private float initialVelocity;
    4.     private float velocity;
    5.     private void jump()
    6.     {
    7.         initialVelocity = Mathf.Sqrt(-2.0f * gravity * jumpHeight);
    8.         velocity = initialVelocity;
    9.     }
    10.     private void Update()
    11.     {
    12.         if (Input.GetMouseButtonDown(0))
    13.         {
    14.             transform.position = Vector3.zero;
    15.             jump();
    16.         }
    17.         if (velocity > 0)
    18.         {
    19.             // Δx= v0*t + (1/2)*a*t²
    20.             float displacement = velocity * Time.deltaTime + 0.5f * gravity * (Time.deltaTime * Time.deltaTime);
    21.  
    22.             // Apply gravity to the velocity
    23.             velocity += gravity * Time.deltaTime;
    24.             // Move the ball based on the current velocity
    25.             transform.Translate(Vector3.up * displacement);
    26.         }
    27.     }
    If you apply gravity to the velocity first, you are displacing the object as if it moved the entire frame time at that final velocity, which is not true: if you were to increase the framerate by 1000x, the velocity at each of these sub-frames would be different because it changes due to the acceleration at each step.

    That formula calculates the sum of the displacement of "infinitely small" sub-steps between the previous velocity and the new one. Since gravity is constant, velocity increases linearly and the sum of the displacement of infinite sub-steps can be calculated precisely by taking the average of the old and new velocity values (aka: the integral).

    For reference:
    https://www.khanacademy.org/science...ic-formulas/a/what-are-the-kinematic-formulas
     
    fataldevelop likes this.
  4. fataldevelop

    fataldevelop

    Joined:
    Jul 5, 2014
    Posts:
    17
    Wow, you solved the problem perfectly, now the given jump height is reached at any frame rate. I'm lacking some kinematic formulas, have to dive into, thank you Sir
     
    Last edited: Jun 8, 2023