FixedUpdate() + delta time... why? (Related to tutorial project.)

I’ve done quite a lot of programming in my days, but I’m new to Unity, so I’m currently going through the tutorial projects to get a feel for how things work. They’ve been really helpful so far, but one part of this one has me a bit confused.

So, it’s about making this ball roll around by applying force to it using AddForce(). This is done inside FixedUpdate(), which makes sense. What I don’t quite get is the deltaTime multiplication here:

rigidbody.AddForce(movement * movementSpeed * Time.deltaTime);

The voice-over says it’s to make the input “smooth and framerate-independent”, but… isn’t FixedUpdate() already framerate-independent? Isn’t the entire point of it that it updates at fixed time steps rather than being affected by framerate like Update() is? Can the delta time inside FixedUpdate() actually vary?

I’ve searched for answers to this question, but haven’t really found anything clear on this specific matter of combining FixedUpdate() with deltaTime.

Thanks in advance!

EDIT: Should I have posted this in the Answers section? Sorry in that case, as I said I’m new!

I wondered this too, actually.

I think it might just be as a safeguard - FixedUpdate() is indeed framerate-independent already, but in case for some reason something happens and it varies, it’s a good idea to use Time.deltaTime as a failsafe.

Although I could be wrong, and it might just be an error from the tutorials?

FixedUpdate is called every physics step, so I’m (almost) entirely sure the use of Time.deltaTime is simply wrong here.

A detail that everybody doesn’t know is that it is correct to use Time.deltaTime even in FixedUpdate (As explained here you don’t have to use Time.fixedDeltaTime). Still, in this particular case it shouldn’t have been used at all.

Is FixedUpdate absolutely guaranteed to run on a fixed timestep? If you have code that takes too long to execute, wouldn’t it be possible for FixedUpdate to run slower than 60 times per second? I think that’s the reason for the deltatime usage… it’s just an extra step in case something is causing it to run slowly (such as a garbage collection for example).

Hmm, yeah, could be something like that I guess. But the way he explains it in the video still doesn’t really make sense to me.

I was aware of that actually. But when would you use it?

Yeah, I thought about that too. Makes the most sense I guess! So in that case you should actually always use it? You never know how something’s gonna run on someone else’s computer, etc.

In FixedUpdate Time.deltaTime returns the fixed timestep.

With that in mind, if we had cut the fixed time step in half, that function would be called 2x as much. Since Time.deltaTime returns the new fixed time step (half of the original) the end result is the same. It serves the same purpose as Time.deltaTime in the Update function, except it’s for when YOU change the fixed time step rather than the computer being unable to keep up.

That makes a lot of sense in theory, but when testing it this isn’t actually what happens. Without the deltaTime multiplication, changing the fixed timestep doesn’t change the speed of the physics simulation. For example, going from the default of 0.02 to 0.08 only makes it a lot choppier, the velocity of the rolling ball doesn’t seem to change. So it looks like the physics engine already takes the timestep into account, without you explicitly doing anything about it. However, when doing the deltaTime multiplication, like in the tutorial, changing the fixed timestep does change the physics simulation quite a bit. With a timestep of 0.08 (which, as you say, should just be cancelled out by the deltaTime multiplication) the simulation runs both choppier (of course) and faster. The ball just goes flying across the “level”, and typically fails to even collide with the walls, instead just going right through. This, again, doesn’t happen if the deltaTime multiplication is left out (well, the missed collisions do eventually happen if you increase the fixed timestep even more, but the speed still stays the same).

So yeah, it definitely looks to me like the physics engine already takes the timestep into account, even as it’s changed, and doing the multiplication only serves to mess things up.

Typically Time.deltaTime is used to move an object in side of Update() at a determined speed. In Unity speed is typically considered to be represented in meters, as one Unity unit is one meter. If an object is moving along it’s Z axis at 1 * Time.deltaTime this would be one meter per second.

function Update(){
YourObject.transform.forward * (10 * Time.deltaTime); //Move at ten meter per second along it's forward direction.
}

http://docs.unity3d.com/Documentatio...deltaTime.html

The physics engine uses Time.fixedTime;
http://docs.unity3d.com/Documentatio...fixedTime.html

In Rigidbody Physics speed / velocity is controlled similarly but Time.deltaTime is not required because the physics engine assumes the input value given is in meters per second.

function FixedUpdate(){
YourObject.rigidbody.velocity = Vector3.forward * 10; // Set the object velocity to be 10 meters per second in it's forward direction. 
}

http://docs.unity3d.com/Documentatio…-velocity.html

The Rigidbody.AddForce() however does not work in the same way. Imparting force onto an object will not make the object move at that speed. Instead you are providing an impulse of force with the amount of whatever you specify. Then depending on the objects weight and friction the objet will move.

function FixedUpdate(){
YourObject.rigidbody.AddForce(Vector3.forward * 10); // Apply 10 units of force to the object along it's forward axis.
}

http://docs.unity3d.com/Documentatio....AddForce.html

If a physics simulation looks like it is shuddering this can be because of a few things. The physics update is set to a low value. Increasing the update will calculate physics more times per second. Also the physics interpolation may be disabled. Interpolation will try to simulate what is happening between physics updates to make things appear smoother.

http://docs.unity3d.com/Documentatio...meManager.html
http://docs.unity3d.com/Documentatio...rpolation.html

1 Like

Huh. I’m starting to wonder if the multiplication in the tutorials is what was causing issues in my project (based off of the same tutorial series).

I think Unity should update that video and let everybody know it’s redundant - I wouldn’t have thought that much about it if it hadn’t been for this thread (although I did wonder why I needed to add it in despite FixedUpdate() using it already).

Sorry for the bump, but I just did some experiments.

I rewrote the script the tutorial has you write for player movement to not use Time.deltaTime (and also rewrote it in JavaScript), and tried a very, very small number for movement speed (10f) that I set in the Inspector, rather than the 500f the guy sets in the video. There’s also some game-specific code I threw in as a test (decided to kill two birds with one stone :stuck_out_tongue: ).

Here’s the script:

#pragma strict


// Declare public variables to be set in inspector
var lives   : int;
var score   : int;
var health  : float;
var moveSpeed : float;
var moveEnabled : boolean;


// If a new level was loaded, get previous lives, score  and health data
function OnLevelWasLoaded(level : int)
{
    lives = PlayerPrefs.GetInt("lives");
    score = PlayerPrefs.GetInt("score");
    health = PlayerPrefs.GetFloat("health");    
}


// Use FixedUpdate()
function FixedUpdate () 
{
    // Store input axis' in variables
    var moveVertical : float = Input.GetAxis("Vertical");
    var moveHorizontal : float = Input.GetAxis("Horizontal");
    
    // Store move information in movement vector
    var movement = Vector3(moveHorizontal, 0.0, moveVertical);
    
    // Apply movement
    if(moveEnabled)
    {
        rigidbody.AddForce(movement * moveSpeed); 
    }
}

I also set Angular Drag up to 0.25 to ensure the player wouldn’t go flying super-fast. When I ran the program, despite having a very small movement speed, the sphere moved around the level at what felt to be a very good pace - it was smooth and easily controllable!

However, when I did multiply the movement vector by Time.deltaTime, it suddenly slowed to a crawl - I had to put the number back up to 500 in order to get anything to feel even remotely right!

So the Roll-A-Ball series needs to be updated to fix the following:

  • Teach the person watching the tutorial about Angular Drag and how it can help prevent massive amounts of flying and dying.
  • !!!DO NOT!!! multiply the movement by Time.deltaTime inside of an already fixed update loop, as it results in oddities and the need to increase movement speeds by a huge magnitude.

So, that’s what my experiments concluded. Attached is the demo scene I quickly put together! Move left and right to see what I mean.

1495364–83785–$Gravity Ball.zip (133 KB)

That’s because you’re multiplying by a small number - Time.deltaTime will be something in the vicinity of 0.02. So having to make your number 50x bigger to get the same result is in fact 100% correct and is exactly what you should expect.

Having not downloaded and run your demo, what “oddities” are you referring to? And what is the other code (“killing two birds with one stone…”) that you’re not telling us about that you also changed? And how can we be sure that there are no bugs in your porting?

I am absolutely sure that this conclusion is incorrect. And I’ve been doing this stuff for ages without issue.

I mean, sure, you don’t need to multiply by Time.deltaTime specifically to make the code framerate independent, because it already is. But it shouldn’t hurt as you’re saying it does, because adding a constant multiplier shouldn’t be an issue. And in terms of code maintenance that constant multiplier can make your life a heck of a lot easier, so it’s not at all redundant - for instance it’ll “just work” if you decide to change the physics timestep, or if you write generic functions that you want to be able to call from both Update() and FixedUpdate() on different objects.

Apologies, I should’ve been more clear.

My other code was for another project I’m working on and I needed to test the “OnLevelWasLoaded()” function, which is why it’s in the code snippet I originally posted. It doesn’t do anything at the moment, it just sits there for the time being.

I also realize that multiplying by Time.deltaTime would then require a larger number for the same result in speed - it’s just that multiplying by Time.deltaTime is completely unnecessary inside of an already fixed loop. My point was that not every beginner is going to realize that, and might be confused.

As for the “oddities”, because of needing to have much higher numbers when multiplying by Time.deltaTime, the velocity of the object would sometimes be inconsistent - I don’t know if it was just on my Mac or because the multiplication is a redundancy, but either way, sometimes it would fly really fast, sometimes it would take a few seconds to get going - that’s why I messed with the Drag/Angular Drag settings in the Rigidbody component and found that using them and completely eliminating the multiplication by Time.deltaTime gave much more consistent and smooth results.

How would multiplying by Time.deltaTime make this “easier” like you say? If anything, I found it caused the issues I said above.

No, it isn’t “completely unnecessary”, its purpose just isn’t the same as it is in a variable-duration game loop (ie: Update()).

In a variable duration game loop you multiply a time delta into calculations so that they happen at a constant speed in relation to the passage of time.

In a fixed-duration game loop you multiply by a time delta to give yourself more control and flexibility. Please note that from a mathematical point of view you’re doing this implicitly in any case with a fixed value of 1.0. The thing is that a fixed value of 1.0 doesn’t help you out in any way, where a variable value can help you a lot - and I did already give two great examples of why.

  • If you need to change the fixed timestep duration, you don’t need to change all of your calculations to match.
  • You can use time-dependent functions in common between the fixed and variable loops.
  • All of your values in your calculations, Inspector properties, etc. are easier to understand because they’re all “per second” instead of “per arbitrary physics tick”.