Search Unity

  1. We are migrating the Unity Forums to Unity Discussions. On July 12, the Unity Forums will become read-only. On July 15, Unity Discussions will become read-only until July 18, when the new design and the migrated forum contents will go live. Read our full announcement for more information and let us know if you have any questions.

Resolved Should I Use Time.deltaTime with the .AddForce() Function to Make the Motion Framerate-Independent?

Discussion in 'Physics' started by tszkoda, Mar 15, 2023.

  1. tszkoda

    tszkoda

    Joined:
    Jan 13, 2022
    Posts:
    2
    Hello,

    I am following one of the Unity Junior Programmer lessons, in which we are creating a prototype with a spherical player game object that can be controlled by adding Rigidbody forces. I noticed that my player moved much faster than the one showed in the lesson, even though I had used the same values, which led me to believe that it was my higher-framerate monitor that was causing the difference. However, I thought that when using the Rigidbody .AddForce() function, you didn't need to multiply the value by Time.deltaTime. Was I mistaken? Or is there a different way I should go about making physic forces framerate-independant?

    Here's a snippet of my code:

    Code (CSharp):
    1. void Update()
    2.     {
    3.         float forwardInput = Input.GetAxis("Vertical");
    4.  
    5.         //move the player foward and backward in the direction of the focal point
    6.         playerRb.AddForce(focalPoint.transform.forward * forwardInput * speed);
    7.     }
     
  2. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    5,251
    Have you tried adding it and running the game oa different fps with Application.TargetFramerate?

    I think you should add it. If you push something 5 times a second it has leff force them if you push the same amount 50 times a second
     
  3. lightbug14

    lightbug14

    Joined:
    Feb 3, 2018
    Posts:
    447
    For this, it is recommended to use FixedUpdate instead of Update. Even though delta time might help, you'll end up using the wrong units.

    I'd recommend reading this --> documentation
    "ForceMode.Force: Interprets the input as force (measured in Newtons), and changes the velocity by the value of force * DT / mass. The effect depends on the simulation step length and the mass of the body."

    This means that the body will apply a velocity change (delta velocity) of:
    dv = F (dt / m) ... (F = m * a)
    F is the argument you pass in, which is a force of course (Forcemode = force).
    For instance, if you want to add 3 Newtons forward, then the code could be as simple as this:
    Code (CSharp):
    1. rb.AddForce(transform.forward * 3f);
    Now, If you want to make the rb move at a certain target velocity (i'm ignoring drag/friction), then you need to find the force required for that using the formula from above.

    For example, the following code moves the body forward at a speed = MoveSpeed. Notice how all different modes do the exact same thing.
    Code (CSharp):
    1. public class AddForceExample : MonoBehaviour
    2. {
    3.     public float MoveSpeed = 6f;
    4.     public ForceMode ForceMode;
    5.  
    6.     Rigidbody rb;
    7.  
    8.     void Awake() => rb = GetComponent<Rigidbody>();
    9.  
    10.     void FixedUpdate()
    11.     {
    12.         // this will force the script to recalculate deltaVelocity every frame
    13.         // Otherwise, delta velocity will be zero once the speed is reached
    14.         rb.velocity = Vector3.zero;      
    15.      
    16.         Vector3 targetVelocity = MoveSpeed * transform.forward;
    17.         Vector3 dv = targetVelocity - rb.velocity  // Velocity change required
    18.         float dt = Time.fixedDeltaTime;
    19.  
    20.         // force = rb.mass * (dv / dt);
    21.  
    22.         switch (ForceMode)
    23.         {
    24.             case ForceMode.Force:   // f = m * (dv/dt)
    25.                 rb.AddForce(rb.mass * (dv / dt), ForceMode.Force);
    26.                 break;
    27.             case ForceMode.Acceleration:  // a = dv/dt
    28.                 rb.AddForce(dv / dt, ForceMode.Acceleration);
    29.                 break;
    30.             case ForceMode.Impulse:   // imp = m * dv
    31.                 rb.AddForce(rb.mass * dv, ForceMode.Impulse);
    32.                 break;
    33.             case ForceMode.VelocityChange:  // dv
    34.                 rb.AddForce(dv, ForceMode.VelocityChange);
    35.                 break;
    36.         }
    37.     }
    38. }
     
    Last edited: Mar 16, 2023
  4. tszkoda

    tszkoda

    Joined:
    Jan 13, 2022
    Posts:
    2
    Thank you for the explanation. I appreciate the help!