- Home /
What is the reason of FixedUpdate() being invoked more than 1 time on low framerate ?
I know that FixedUpdate() runs every 0.02 sec (50 times in total for 1 second). But what if by some reason FPS will drop to 10 frames for example and will stand 10 FPS for awhile... Then FixedUpdate() will be invoked 5 times per a frame, right ? But what is the truly purpose of doing that ? Why it's not enough to call FixedUpdate() only once in such case and discard others 4 (especially when we are talking about physics when it's important to get the latest changes at the moment) ? I'm sure this question more suitable for the Unity engine developers. But maybe I'm missing something ? What is the reason of such behavior ? Any ideas ?
Answer by Edy · 4 days ago
Because physics and other systems (i.e. gameplay) must use a constant delta time to be consistent. It's not only about the number of times FixedUpdate is called per visual frame, but most importantly every call will be performed with the same delta time, by default 0.02 (50 Hz). Otherwise, these systems would be inconsistent when frame rate drops.
For example take a physics rigidbody that moves at 50 m/s, let's say it's a fast car. At that speed moves 1m on each physics step (FixedUpdate). Suppose the car is 4m long. At one physics frame the car can be at one side of the road guardrail, and the next frame it can be at most 1m behind the guardrail. So the physics engine can detect the collision of the car with the guardrails at that speed without issues.
What if we call FixedUpdate 10 times per second as you propose? This means a delta time of 0.1, so the car moves 5m on each physics step. At one frame it can be at one side of the guardrail, but the next frame the car may be entirely at the opposite side of the guardrail without the collision being detected.
So instead of doing so, when the visual frame rate drops Unity keeps calling FixedUpdate many times when necessary. The next visual frame will display the car after having collided properly with the guardrail. You would have lost a few visual frames and effects only, but the physics result (and the gameplay) will be the same regardless the fps. This logic is applicable to anything requiring consistency: character controller, jumps, bullets, AI, ...
Here's a quick an convenient guide about Update and FixedUpdate:
https://forum.unity.com/threads/update-vs-fixed-update-vs-late-update.307235/#post-5114657
Here's a detailed example of physics inconsistencies when changing the fixed delta time: https://forum.unity.com/threads/adjusting-time-fixeddeltatime-by-time-timescale.869491/#post-6796637
@Edy, Thank You! I was thinking about the collision detection in exact way. So in the provided scenario with car and 10 FPS FixedUpdate()'s logic can be:
No collision
No collision
Collision Detected (Memorize the collision)
Collision Detected (Do some collision stuff)
Collision Detected (Do some collision stuff) ?
I am just trying to come up with a good example of such usage.
But, what if Update() method will take long execution time (longer than 0.02 sec for our example), is there will be a chance of missing the collision as the Update() and FixedUpdate() methods are executed on the same CPU thread ? And then FIxedUpdate() interval will not be approximately equal to 0.02 sec, it should be more after this long Update() ?
The key is that all FixedUpdate() calls will be forcefully performed, no matter any other considerations. If Update() takes too long, then the pending FixedUpdate() calls will still be performed afterwards. The execution time will be larger than the in-game time, so as result we will see the game time slowing down.
If we have FixedUpdate running at 50 Hz but only 10 FPS then Unity calls FixedUpdate() 5 times between each Update() call. These 5 FixedUpdate() calls are consecutive without wait intervals. The trick here is that the code within FixedUpdate "sees" a deltaTime of 0.02 so the calculations and in-game time are fully consistent, even when the actual realtime intervals not being 0.02.
Collisions require the colliders to be in contact within a given physics step. In the example of the car with physics running at 10 fps there's a situation where colliders never enter in contact because the car's position is updated to a position behind the other collider in a single physics step. So collision is not detected. The only way to keep collisions consistent is running 5 physics steps for each visual frame, as described above.
If I got it right, then there are two ''kinds'' of timelines: physics consistent time (which FixedUpdate() uses) and Real-time ? And in any case (poor in performance) where Update() can be executed for a long time (more than 0.02 sec), FixedUpdate() will follow this consistent timeline ? Then being called every 0.02 sec despite the REAL elapsed time ?
// For example:
// 10 FPS
// Previous frame
FixedUpdate()
// Let it be: Before this method all FixedUpdate's were executed.
// But this Update() took 1 second, then 50 FixedUpdate's should be called before
// next Update() method
// With this first FixedUpdate() deltaTime will be also 0.02 sec ?
// Despite the fact that between this FixedUpdate() and last FixedUpdate() there
// was Update() which took 1 second ? And then by real-time it should be 1.02 sec ?
FixedUpdate() // dt - 0.02
FixedUpdate() // dt - 0.02
FixedUpdate() // dt - 0.02
....
....
// Next Update()...
Update()
In your guide you have some misleading phrasing. Update calls are never skipped. FixedUpdate could be "skipped" if the visual framerate is high enough so no FixedUpdate call is necessary in between two Update calls. Everything is happening at the Update rate in any case. FixedUpdate is just called either multiple times a frame, once or not at all in a frame. But no matter what you get your 50 calls per 1 second of ingame time. You're correct that Unity would slow down the ingame time if the framerate drops below 3fps since the max timestep is set to 0.333333. If the actual realworld deltatime is greater than the max timestep, deltaTime is simply clamped to the max timestep which would cause the ingame time to run slower than the realworld time.
So if for example you have an extreme high load and it takes half a second to complete a frame, deltaTime would report 0.333333. That means after 3 seconds of realtime we would have rendered 6 frames but only 2 seconds ingame time would have passed. So time slows down due to the dt clamping. This clamping is important because if the cause for the slow down is inside FixedUpdate or physics, the situation would spiral into extremes. So when 50 physics cycles take longer than 1 whole realworld second, Unity would have to cram more and more fixedupdate calls into a single frame. That's why there has to be a limit.
I once created this CustomFixedUpdate class which you can use to implement your own seperate fixed update method(s) with whatever call count you want. You can implement timers that run just once every minute, once every second or 10000 times a second. It just takes care of calling the method for you when necessary. Of course it can not slow down time, however since we also depend on Unity's deltaTime we have already a guard there. Though you can specify a max timestep to limit the execution time.
It's just the opposite: Update calls may be skipped, resulting in less Update calls with larger delta time each. FixedUpdate calls are never skipped. Given a fixed delta time of 0.02, then there will be a FixedUpdate call for all and every single fixed time step: t = 0.00, t = 0.02, t = 0.04, t = 0.06, t1 = t0 + 0.02. None of these fixed time steps will ever skip its FixedUpdate call, and deltaTime will always be 0.02.
Also in the case of extreme high loads. All and every FixedUpdate calls for their corresponding fixed time intervals will be performed with dt = 0.02. In these cases Update calls are massively skipped (in the sense of visual frames skipped), and when called it receives a large dt, to a limit as you mention. This may result in less FixedUpdate calls per second, but all them will always keep the deltaTime = 0.02. Internally the game runs consistently, but externally we see the game time slowed down
.
Indeed, your CustomFixedUpdate class is almost exact to what Unity does with Update and FixedUpdate. Maybe you misunderstood something in my guide, or I didn't explain something correctly? It makes sense as seen from the user side, writing code in Update and FixedUpdate.
No, "Update calls" can't be skipped because they are part of the main application loop. You always get one Update per frame. Nothing is ever skipped when it comes to Update. If a frame takes 10 seconds to render you still get one Update call per frame which mean 1 call per frame. So I have absolutely no idea what you mean by skipping an Update call. One iteration of the main application loop is as fast as the application can run and no Update is ever skipped. Yes, FixedUpdate calls are not "skipped", but with a fixed dt set to 0.02 you will never get more than 16.66 FixedUpdate calls per frame because deltaTime would be capped. All FixedUpdate does is catch up to the virtual game time at fix interval steps (fixedDeltaTime). However if the game time slows down, the FixedUpdate calls would slow down as well since they only ever catch up to the game time.
FixedUpdate calls are those which can be skipped at high framerates. This is exactly what causes the common input issues when people check for KeyDown events in FixedUpdate. At a framerate of 200 fps only ever 4th frame you get one FixedUpdate. So I don't understand your reasoning about "skipping". Everything that matters to a game, Input processing, animation, Update, rendering happend once per frame in order. When you say that Update is skipped, what is happening when it's skipped? Skipping means you don't do what you normally do and do something else instead. This is not the case. Unity processes frame by frame. If a frame takes a minute to process and another 10 minutes to render then a frame would take 11 minutes. Still nothing got skipped.
However since FixedUpdate has a fix limited calls per second, if the framerate is high and the application loop comes to the point where it usually processes physics, it would skip the physics step and continues processing the next frame.
Yes all FixedUpdate calls per ingame time are called, that's the point of having a fixed update. You seem to have the idea that the fixed time is somehow THE game time. That'S not true. The fixedtime is just dragged along. The physics loop does as many fixed update calls as necessary to catch up to the game time, that's all.
[1]: https://docs.unity3d.com/Manual/ExecutionOrder.html
Answer by Bunny83 · 4 days ago
The point of fixedupdate is to have a constant call count per second. Any linear calculations can be framerate adjusted by using deltaTime. However Any kind of calculation that is not linear can not be compensated with deltatime. In physics when you have a constant acceleration the velocity would change linearly. Using deltaTime would result in correct velocity values each frame. However the position in turn is linearly adjusted by the velocity and indirectly by the square of the acceleration. This is never accurate. It would require an infinitely high framerate to get accurate results. This is of course not possible. Instead we ensure a framerate of 50 fps to ensure the same results independent of the framerate.
Just as an example compare the results of just using deltaTime with a framerate of 20 and a framerate of 5 compared to the physical accurate result of a contant accelerated movement:
// t acc vel10 pos10 vel5 pos5 velR posR
// --------------------------------------------------------------------
// 0.0 2 0 0 0 0 0 0
// 0.1 2 0.2 0.02 0.2 0.01
// 0.2 2 0.4 0.06 0.4 0.08 0.4 0.04
// 0.3 2 0.6 0.12 0.6 0,09
// 0.4 2 0.8 0.2 0.8 0.24 0.8 0.16
// 0.5 2 1.0 0.3 1.0 0.25
// 0.6 2 1.2 0.42 1.2 0.48 1.2 0.36
// 0.7 2 1.4 0.56 1.4 0.49
// 0.8 2 1.6 0.72 1.6 0.8 1.6 0.64
// 0.9 2 1.8 0.9 1.8 0.81
// 1.0 2 2.0 1.1 2.0 1.2 2.0 1.0
// 1.1 2 2.2 1.32 2.2 1.21
// 1.2 2 2.4 1.56 2.4 1.68 2.4 1.44
// 1.3 2 2.6 1.82 2.6 1.69
// 1.4 2 2.8 2.1 2.8 2.24 2.8 1.96
// 1.5 2 3.0 2.4 3.0 2.25
// 1.6 2 3.2 2.72 3.2 2.88 3.2 2.56
// 1.7 2 3.4 3.06 3.4 2.89
// 1.8 2 3.6 3.42 3.6 3.6 3.6 3.24
// 1.9 2 3.8 3.8 3.8 3.61
// 2.0 2 4.0 4.2 4.0 4.4 4.0 4.0
// 2.1 2 4.2 4.62 4.2 4.41
// 2.2 2 4.4 5.06 4.4 5.28 4.4 4.84
// 2.3 2 4.6 5.52 4.6 5.29
// 2.4 2 4.8 6.0 4.8 6.24 4.8 5.76
// 2.5 2 5.0 6.5 5.0 6.25
// 2.6 2 5.2 7.02 5.2 7.28 5.2 6.76
// 2.7 2 5.4 7.56 5.4 7.29
// 2.8 2 5.6 8.12 5.6 8.4 5.6 7.84
// 2.9 2 5.8 8.7 5.8 8.41
// 3.0 2 6.0 9.3 6.0 9.6 6.0 9.0
Note vel10 / pos10 is the velocity / position at a framerate of 10 fps while vel5 / pos5 is the same at a framerate of 5 fps. The last column is calculated using the actual formula of constant accelerated movement p(t) = 0.5 * a * t²
where "t" is the absolute time passed. As you can see the lower the framerate the greater the error after just 3 seconds. Also note the velocities are all correct since it grows linearly.
There is a trick to actually get the correct results for constant accelerated movements. However in physics simulations we even have changing accelerations like drag or spring forces which are not constant and those are impossible to "fix" with delta time. So FixedUpdate just provides common ground no matter the framerate because you always get the same call count and all physics calculations are always equally "off", but at least consistent.
Your answer
Follow this Question
Related Questions
[C#] Game runs oddly slow 2 Answers
iOS FPS low frame rate when character moves, profiler shows Physics.Simulate takes cpu time 0 Answers
Applying Forces, independent of Frame Rate? 1 Answer
Noticeable difference between full-screen / windowed physics behavior in standalone build 0 Answers
transform.position in fixedUpdate() different from transform.position in Update(); 1 Answer