StartCoroutine and Time.fixedDeltaTime

I have in 2D in FixedUpdate a StartCoroutine which rotates an enemy in time. My problem is, if I have 144fps it works and the rotation is animated but if I set to no FPS-limit (4000fps) the rotating is immediatly and not animated (to fast to see). I don’t understand this, because I have set the fixed-Timestep to 100 fps. So why it is not constant and independent from the current framerate?

My code:

    IEnumerator RotateCoroutine(int toAngle, float fromAngle, float inTime)
    {
        float angleAround;
        angleAround = (((float)toAngle - fromAngle) * Time.fixedDeltaTime) / inTime;
    
        for (var t = 0f; t < 1f; t += Time.fixedDeltaTime / inTime)
        {
        transform.RotateAround(rotatingPos.transform.position, Vector3.forward, angleAround);
            yield return null;
        }
    }

Coroutines execute immediately after Update(). They’re not independent of the main loop regardless of where you start them from.

https://docs.unity3d.com/Manual/ExecutionOrder.html

FixedUpdate() is a complete sham. It’s just faking independence. It simply executes back-to-back as many times as needed to catch up to where it’s supposed to be, and it starts that process at a specific point in the main loop just before Update().

https://discussions.unity.com/t/530594

Coroutines are NOT a suitable solution for this. I recommend not using them.

Instead, try this ultra-simple pattern for smooth turning over time:

Smoothing movement between any two particular values:

https://discussions.unity.com/t/812925/5

You have currentQuantity and desiredQuantity.

  • only set desiredQuantity
  • the code always moves currentQuantity towards desiredQuantity
  • read currentQuantity for the smoothed value

Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

The code: https://gist.github.com/kurtdekker/fb3c33ec6911a1d9bfcb23e9f62adac4

It’s neither sham nor faking. It does what it’s supposed to do: run at a fixed rate. It simply does not matter if between frames 1 and 2 the FixedUpdate() runs several times right before frame 2, or at evenly distributed time intervals between frames 1 and 2. The end result is the same: anything fixed update does between those two frames will not have a visible effect until frame 2 is rendered and displayed.

Maybe not the best option, but you can yield return new WaitForFixedUpdate() to make the coroutine run at the same fixed rate as FixedUpdate.

You are yielding null, which makes the coroutine wait for the next Update() (see above).

Why would you set it this high? This is wasteful, especially where the game runs at 60 Hz. You’d be doing 40% more work for no benefit. And if you want to smooth things out, you can interpolate animations.

This sentence is missing “… for physics simulations”. Because many people tried to use FixedUpdate for all sorts of things which are real time related and got stumped by getting almost the same timesstamps several times in a row. You are absolutely correct that FixedUpdate aims to meat a certain CPS(calls per second) and it does this as intended. However those calls are not equally spaced. When you want to use them to record snapshots, send network traffic, sync audio and stuff like that the difference may matter.

Unity’s docs page for the method suggests much more than that. The execution order page is the only one that I’m aware of that gets it correct. So within the context of how Unity describes it on the page dedicated to it it’s a sham.

https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html

Btw. If you’re looking for an independed FixedUpdate implementation that works just like FixedUpdate but can run with any fixed CPS rate, you can use my CustomFixedUpdate class (script on github). You can create several fixed update methods with for example 10000 calls per second or 0.1 calls per second. Of course I would not recommend creating fast spinning fixed update loops and if you do, keep the load in those methods as low as possible. That’s because if the framerate drops, the load per frame actually rises since the system tries to keep the set CPS. If the load of that method is the reason for the slowdown, you would end up in a downward spiral you can’t get out of.

Thank you very much, “yield return new WaitForFixedUpdate()” solved this problem.

Excellent callout… “wait for fixed update” is definitely useful for coroutines that interoperate with Physics.

I was more noting that OP appeared to be using a coroutine to:

… which sort of implies that the enemy might turn more than once, might change direction mid-turn, might stop turning halfway through the turn, etc.

ALL of these factors are extremely tricky to handle correctly with coroutines and are the source of a lot of woes, which was really the only point of my “not suitable” comment.