🤔 Unity, huh, how?

🤔

Understanding FixedUpdate

Fixed Update runs only when required. It's run multiple times a frame to catch up to the current time, and it's skipped when ahead.

I like to look at this way: Fixed Update is fake 😲

Fixed Update is run repeatedly until fixed time catches up with game time, and the result is displayed. This keeps the delta time a fixed length (resulting in consistent simulation1), at the cost of fixed time not perfectly aligning to real time.
For example, you could advance Fixed Update 1 / Time.fixedDeltaTime times to move it forward by a second. That can be done in an instant, ignoring real time, and that's what Fixed Update is doing.

information

You can read Unity's version of this description in the Important Classes - Time section of the scripting manual.

Frame diagram example

•••••••••••••••••••0...Fixed UpdateUpdate...1Fixed UpdateUpdate...2Update...3Fixed UpdateFixed UpdateUpdate...Frame no.Main thread
See that Fixed Update may run multiple times a frame, or not at all.

You can use the timeline view of the Unity Profiler to see what is actually occuring in your frame.

information

FixedUpdate isn't the only code running at this fixed rate.
You can see an expanded version of a frame in the Unity documentation: order of execution for event functions.

Don't think about Update and FixedUpdate as executing in parallel, because it is completely linear.
Background threads do work, including scheduling rendering, performing parallel tasks, and so on. But the execution of your Update/FixedUpdate code is linear.

Fixed Update diagram

Start at the top right dot, and follow the 🔷 choices until the diagram exits.

Time.fixedTime > Time.time
Time.fixedTime <= Time.time
FixedUpdate is run until fixedTime has reached game time.
It may not run at all in some frames.
Fixed Update
Update
Time.fixedTime += Time.fixedDeltaTime
Update is run every frame.
This logic is simplified for consumption. Unity provide their own time logic diagram.
The native Unity source is not public, so we can't see the code. Entities implements similar logic in RateUtils.FixedRateCatchUpManager.

Notes

Input in FixedUpdate

Because FixedUpdate is not guaranteed to run every frame, this makes it a very poor place to poll instantaneous input.

Maximum delta time

Time.maximumDeltaTime bounds the number of times fixed update can run due to a this limit on the amount of time that can pass in one frame2. This helps prevent a fixed update cascade, where the cost of running many fixed updates to catch up causes the frame time to rise, which in turn causes more fixed updates.

  1. If you want to understand why variable time is complicated, Unity has written some complex blogs like fixing Time.deltaTime in Unity 2020.2 for smoother gameplay: What did it take?

  2. This is a virtual time limit. The frame will still take the same amount of real time to run.