0
\$\begingroup\$

Most of the time when I use FixedUpdate I dont add Time.fixedDeltaTime, but is that something I should do? Because we have Time.deltaTime in Update which is for making sure that your game runs frame independent, right? So it doesn't matter if you have 50 or 500 fps.

But what about Time.fixedDeltaTime in FixedUpdate, are you supposed to use it when moving your objects with their rigidbody?

I created this simple code which moves the rigidbody with AddForce:

[SerializeField] private float _speed;
[SerializeField] private Rigidbody2D _rb;
[SerializeField] private bool _isUsingfixedDeltaTime;

void FixedUpdate()
{
   if(_isUsingfixedDeltaTime)
    {
        _rb.AddForce(new Vector2(_speed * Time.fixedDeltaTime, 0));
    }
   else
    {
        _rb.AddForce(new Vector2(_speed, 0));
    }
}

It just adds a force to your rigidbody and you can choose between using fixedDeltaTime or not. If I am not wrong fixedDeltaTime gives back how many seconds it takes each time to run FixedUpdate, which is 0.02 seconds. So all we are doing is multiplying speed with 0.02. But what's the point to that if FixedUpdate is always called every 0.02 seconds? Isnt it the same without it? FixedUpdate gets called as many times on a ps with low fps as on a pc with high fps, right?

\$\endgroup\$
2
  • \$\begingroup\$ FixedUpdate is always called every 0.02 seconds... until you decide to change it. For instance, maybe halfway through the project you find you have collision glitches and need to move to a more frequent physics tick to resolve them. Or maybe you find the game runs too slow on low-end hardware (say when porting to Switch, mobile, or web) and you need to move to a longer physics step to reduce the computational load. When that happens, do you want to have to re-tune all your physics parameters to return to the same game feel? Or do you want the code to auto-adapt correctly to the new timestep? \$\endgroup\$
    – DMGregory
    Commented Jul 4 at 18:28
  • \$\begingroup\$ This code is incorrect for other reasons that I explain in the answer below. But in general it is a good idea to use deltaTime to make your calculations framerate independent, even when running at a fixed framerate, to avoid creating technical debt where changing that fixed rate down the line would require a massive re-tuning pass. \$\endgroup\$
    – DMGregory
    Commented Jul 4 at 18:30

1 Answer 1

1
\$\begingroup\$

You almost never have to use Time.fixedDeltaTime specifically .

That's because Time.deltaTime is a getter property, and if you use it in any method that gets called during the physics step (FixedUpdate, OnCollision/TriggerEnter/Exit/Stay, coroutines resuming after a WaitForFixedUpdate etc), it automatically returns Time.fixedDeltaTime anyway. So it suffices to use Time.deltaTime whenever you want a time delta, and the right one will be selected for you automatically, based on what part of the update loop is running your code.

So the real question is: when should you multiply by a time delta?

You can answer this with dimensional analysis, which is just a fancy way of saying "make sure your units make sense".

So, let's say you have a speed. That's measured in metres per second (\$\frac m s\$). If we multiply by a time delta in seconds (\$s\$), we get \$\frac m s \times s = m\$ a value in metres (a displacement). That answers the question "How far should an object move, if it travelled at speed \$v\$ for duration \$\Delta t\$?"

But you're passing this to AddForce, which expects a force measured in Newtons (\$N = \frac {kg \cdot m} {s^2}\$), so these units do not make sense, and we know we wrote the wrong code here.

To convert a speed into a force, we need to know "how heavy is the object we want to accelerate up to that speed?" and "how long should it take to accelerate to that speed?"

So you could use code like this:

void FixedUpdate() {

    float mass = _rb.mass;
    float accelTime = 1f; // Replace with your preferred duration.

    Vector2 velocity = new Vector2(_speed, 0);
    Vector2 force = mass * velocity / (accelTime * accelTime);

    _rb.AddForce(force);
}

Running our dimensional analysis, you can confirm we end up with \$\frac {kg \cdot m} {s^2} = N\$, so our units make sense as a force now.

Notice that we did not need to use a time delta for the duration of the frame/physics step at all. That's because we're applying a force, which pushes just as hard at any simulation rate. The physics engine is then responsible for integrating that force over whatever duration it's simulating this tick to produce the appropriate velocity and position changes.

We mainly need to use time deltas when we're doing that integration ourselves, calculating our own change in velocity, position, charge, money, HP, or other quantity from a rate of change without delegating that calculation to the physics engine.

\$\endgroup\$
3
  • \$\begingroup\$ Note that the "speed" parameter here is really just the speed you'll move after 1 second of acceleration. Accelerate longer, and you'll be going faster than that speed. If you want to accelerate up to but not beyond a given speed, you can use a method like this. Note how there we do need to use a time delta, because we need to account for "how much should my speed change in this frame?" \$\endgroup\$
    – DMGregory
    Commented Jul 4 at 18:33
  • \$\begingroup\$ First of all thanks for the help with deltaTime, secondly, I have a question. Why do you calculate a force from the speed? All tutorials I have followed(Even Unity's own tutorials where they show you how to use addForce) just put a speed inside of addForce and call it a day, I though the method kinda "Fixed it" by itself. In Unity's doc you can read what calculation each options does: ForceMode.Force "force * DT / mass" But I guess it makes sense that it needs a force, because it tells you that its a force in the docs and in Unity... \$\endgroup\$
    – MrV
    Commented Jul 8 at 16:16
  • \$\begingroup\$ It's sadly easy to find terrible Unity advice online, including from Unity themselves in this case. For my way of working, when I'm tuning the behaviour parameters on a script, it's important that I have a clear understanding of what each parameter does, and how changing them will affect play. Otherwise I'm liable to make the wrong changes and have an awful time debugging. So if it says "speed" in the variable name, it had better darn well be a speed, not a force! If I change the mass of the object, it shouldn't move slower or faster (like it would if my parameter were a force/thrust/torque). \$\endgroup\$
    – DMGregory
    Commented Jul 8 at 16:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .