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

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:

void Update()
    {
        float forwardInput = Input.GetAxis("Vertical");

        //move the player foward and backward in the direction of the focal point
        playerRb.AddForce(focalPoint.transform.forward * forwardInput * speed);
    }

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

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:

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.

public class AddForceExample : MonoBehaviour
{
    public float MoveSpeed = 6f;
    public ForceMode ForceMode;

    Rigidbody rb;

    void Awake() => rb = GetComponent<Rigidbody>();

    void FixedUpdate()
    {
        // this will force the script to recalculate deltaVelocity every frame
        // Otherwise, delta velocity will be zero once the speed is reached
        rb.velocity = Vector3.zero;      
     
        Vector3 targetVelocity = MoveSpeed * transform.forward;
        Vector3 dv = targetVelocity - rb.velocity  // Velocity change required
        float dt = Time.fixedDeltaTime;
 
        // force = rb.mass * (dv / dt);

        switch (ForceMode)
        {
            case ForceMode.Force:   // f = m * (dv/dt)
                rb.AddForce(rb.mass * (dv / dt), ForceMode.Force);
                break;
            case ForceMode.Acceleration:  // a = dv/dt
                rb.AddForce(dv / dt, ForceMode.Acceleration);
                break;
            case ForceMode.Impulse:   // imp = m * dv
                rb.AddForce(rb.mass * dv, ForceMode.Impulse);
                break;
            case ForceMode.VelocityChange:  // dv
                rb.AddForce(dv, ForceMode.VelocityChange);
                break;
        }
    }
}
1 Like

Thank you for the explanation. I appreciate the help!