Search code examples
unity-game-enginegame-physics

When do you multiply by Time.deltaTime in Unity?


There seems to be a lot of confusing/conflicting advice out there about when you should or should not multiply a quantity by Time.deltaTime. So I was wondering, as it pertains to the Unity physics system, when should you multiply by Time.deltaTime?

I understand that Time.deltaTime is used to make certain actions framerate independent, but there are some situations where it isn't clear whether an action is framerate independent. For instance:

  • Doing rigidbody.velocity += acceleration*Time.deltaTime; in FixedUpdate. Since FixedUpdate runs at a constant timestep, does this make the multiply by Time.deltaTime unnecessary?
  • Doing rigidbody.AddForce(force*Time.deltaTime, forceMode);. How do the various ForceModes effect this?

I've seen solutions to individual situations, but it would be nice if there were a simple intuition which could address all of these situations.


Solution

  • The intuition

    Multiplying by Time.deltaTime is used to make an instantaneous operation act in a continuous (or "smooth") way.

    An instantaneous operation will cause a certain quantity to "jump" to a different value. The following operations are instantaneous:

    • Rigidbody.[position|velocity|rotation|angularVelocity] += x;
    • Rigidbody2D.[position|velocity|rotation|angularVelocity] += x;
    • Rigidbody.Add[Force|Torque](x, ForceMode.[Impulse|VelocityChange]);
    • Rigidbody2D.Add[Force|Torque](x, ForceMode2D.Impulse);

    All the above operations cause a quantity to instantly jump by x, irrespective of the length of the frame.

    In contrast, the following operations are continuous:

    • Rigidbody.Add[Force|Torque](x, ForceMode.[Force|Acceleration]);
    • Rigidbody2D.Add[Force|Torque](x, ForceMode.Force);
    • Rigidbody.velocity = x; (continuous from the perspective of Rigidbody.position. i.e. setting the velocity will not make Rigidbody.position suddenly jump to a new value)

    All the above operations are applied over the course of the frame (at least conceptually this happens; what the physics system does internally is out of the scope of this answer). To illustrate this, Rigidbody.AddForce(1, ForceMode.Force) will cause a force of 1 newton to be applied to an object for the entire frame; there will be no sudden jumps in position or velocity.

    So when do you multiply by Time.deltaTime?

    If you are using a continuous operation, you should almost definitely not be multiplying by Time.deltaTime. But if you are using an instantaneous operation, the answer depends on if the operation is being used in a continuous way.

    Example 1: Explosion

    void Explode() {
        rigidbody.velocity += explosionAcceleration;
    }
    

    Here you should not be multiplying by Time.deltaTime since Explode() gets called just once. It is not meant to be applied over a series of frames.

    Example 2: Moving

    void Update() {
        rigidbody.position += velocity * Time.deltaTime;
    }
    

    Here you do have to multiply by Time.deltaTime because the object is supposed to move continuously over time, and you are also using an instantaneous operation. Note that this could be replaced with a continuous operation, and remove the need for multiplying by Time.deltaTime:

    void Update() {
        rigidbody.velocity = velocity;
    }
    

    Although this isn't entirely equivalent to the original, since it ignores the previous value of rigidbody.velocity.

    Example 3: Accelerating

    void Update() {
        rigidbody.AddForce(acceleration*Time.deltaTime, ForceMode.VelocityChange);
    }
    

    Here you should be multiplying by Time.deltaTime because you want the velocity to increase at a consistent rate frame by frame. Note that this is precisely equivalent to:

    void Update() {
        rigidbody.AddForce(acceleration, ForceMode.Acceleration);
    }
    

    This code applies the acceleration over the course of the whole frame. This code is also (in my opinion) cleaner and easier to understand.

    What about FixedUpdate?

    Being in FixedUpdate does not effect any of the above advice. Yes, you could theoretically get away with never multiplying by Time.deltaTime since the time between frames would always be the same. But then all your units would have to be dependent on the fixed frame rate. So for example if you wanted to move at a rate of 1 m/s with 60 frames per second, you would have to add 1/60=.01666 to the position each frame. And then imagine what happens if you change your fixed timestep. You would have to change a bunch of your constants to accommodate.

    Executing code in FixedUpdate does not suddenly make that code framerate independent. You still have to take the same precautions as in Update.

    As a side note, you do not need to replace Time.deltaTime with Time.fixedDeltaTime inside FixedUpdate because Unity already does this substitution.

    Conclusion

    Only multiply by Time.deltaTime if you want an instantaneous operation to act smoothly over a series of frames.

    Many times, you can avoid using Time.deltaTime by using continuous operations, which are often more intuitive (see examples 2 and 3). But this of course depends on the context.