4

I know if I do too many thing in update() the consequence would be dropped frame rate below the target frame rate. But what would happen if I do the same thing in fixedUpdate()?

Would it cause Unity's physicsEngine to mess up, or would it crash the program?

AVAVT
  • 7,058
  • 2
  • 21
  • 44
  • 2
    Some good answers [here](http://answers.unity3d.com/questions/202614/and-yet-more-questions-about-fixedupdate.html) and [here](http://answers.unity3d.com/questions/10993/whats-the-difference-between-update-and-fixedupdat.html) – DeclanPossnett Feb 16 '17 at 13:21
  • @DeclanPossnett So in other words, if I have a 20ms default fixedTimeFrame and my fixedUpdate() take 100ms to run, the game world will be moving 5 times slower than how it should? – AVAVT Feb 16 '17 at 13:43
  • 1
    Basically the _best_ answer on [this unity question](http://answers.unity3d.com/questions/10993/whats-the-difference-between-update-and-fixedupdat.html) explains that you'll normally get the desired amount of physics updates per frame naturally within Unity - but if you put such a great load on the physics engine it wouldn't actually catch up with the frame rate, thus fail to simulate! – DeclanPossnett Feb 16 '17 at 14:30

2 Answers2

2

The answers and comments were very helpful, but they lack a clear, informative answer to my question. Everyone knows bad things will happen when you put too much work load in the FixedUpdate() loop, my question was to ask what bad thing will happen then.

Since I finally got my hand on a computer I decided to make some test on my own. Just for reference this is what I used to test:

public class TestFixedUpdate : MonoBehaviour {
    public int loopNo = 500000;

    private int noOfCall = 0;
    private int collisionTimes = 0;

    private void FixedUpdate()
    {

        if (noOfCall > 100) return;
        float time = Time.timeSinceLevelLoad;

        for (int i = 0; i < loopNo; i++) {
            Quaternion.Slerp(Quaternion.identity, Quaternion.FromToRotation(Vector3.up, Vector3.forward), Mathf.Abs(Mathf.Sin(Time.timeSinceLevelLoad)));
        }

        Debug.Log(Time.timeSinceLevelLoad.ToString("0.00"));

        if (noOfCall > 99) Debug.Log("Simulation finished. Times collided:" + collisionTimes);

        noOfCall++;
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (noOfCall > 100) return;
        collisionTimes++;
        Debug.Log("Times collided:" + collisionTimes);
    }
}

I put it on a sphere that will continuously bounce on a plane. The test was made by changing the function from FixedUpdate() and Update() and compare the differences.

The main difference I found out was that in the case of FixedUpdate(), Unity's simulated Time (the game world's time) is delayed out of sync with actual time. In other words, any function that depends on Unity's Time system will act as if the whole world has slowed down.

Also:

  1. Unity reports the same frame rate for both cases, even though for the FixedUpdate() case it is apparent that the actual frame rate - the frame per real world second - is significantly lower.

  2. Aside from slowing down, collision detection and physics simulation logic seem to work as usual. Bodies that should collide still collide; acceleration, force application etc still work. Rigidbodies that don't jump through a collider in 20ms (Unity's ms) still collide and bounce back as usual.

  3. The Maximum Allowed Timestep option in Project's settings define the maximum amount of (Unity's simulated time) before a frame must be draw (I never knew what it was for before). Clarification: if I set it to 0.5 second, then no matter how much code I put into both functions, the logic update step (Update()) will be called immediately after a FixedUpdate() round has simulated the 0.5-th second, and then the scene will be rendered.

AVAVT
  • 7,058
  • 2
  • 21
  • 44
0

The engine will stall while processing a heavy load (e.g. if you do an infinite loop) inside any function. Things which rely on Time.DeltaTime will start acting up if the frame rate drops too low. It won't really matter whether that's Update or FixedUpdate.

What you can do if you need a process to run a heavy load is to use an coroutines e.g. IEnumerator function and yield, which allows you to split processing over a number of frames, or to have some function called via a callback. e.g. if you have an AI check path 5 times a second you can either handle that in Update with a counter each frame or you can schedule a callback.

Basically, there's going to be limit in how much code you can run per frame without degrading performance. Clever rewriting should make that unnecessary. See if you can cache results of calculations or pre-calculate as much data outside play as possible.

Jason Lang
  • 1,079
  • 9
  • 17