在 fixedUpdate() 中做繁重的工作会有什么后果?

What is the consequence of doing heavy work in fixedUpdate()?

我知道如果我在 update() 中做太多事情,结果会导致帧率低于目标帧率。但是如果我在 fixedUpdate() 中做同样的事情会发生什么?

会不会导致Unity的physicsEngine出错,或者会导致程序崩溃?

在任何函数内处理重负载(例如,如果您执行无限循环)时,引擎将停止。如果帧速率下降得太低,依赖 Time.DeltaTime 的东西将开始起作用。不管是 Update 还是 FixedUpdate 都不重要。

如果你需要一个进程来 运行 重负载,你可以做的是使用协程,例如IEnumerator 函数和 yield,它允许您在多个帧上拆分处理,或通过回调调用某些函数。例如如果你有一个每秒 5 次的 AI 检查路径,你可以在更新中处理它,每帧都有一个计数器,或者你可以安排一个回调。

基本上,在不降低性能的情况下,每帧可以 运行 的代码量将受到限制。聪明的重写应该使它变得不必要。看看您是否可以缓存计算结果或 pre-calculate 游戏外尽可能多的数据。

回答和评论非常有帮助,但对我的问题缺乏清晰、翔实的回答。每个人都知道当你在 FixedUpdate() 循环中放置过多的工作负载时会发生不好的事情,我的问题是问 什么 坏事会发生。

自从终于拿到电脑后,我决定自己做一些测试。仅供参考,这是我用来测试的:

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);
    }
}

我把它放在一个会在一个平面上不断弹跳的球体上。测试是从FixedUpdate()Update()更改函数并比较差异。

我发现的主要区别是,在 FixedUpdate() 的情况下,Unity 的模拟 Time(游戏世界时间)与实际时间不同步。换句话说,任何依赖于 Unity Time 系统的功能都会像整个世界都变慢一样。

还有:

  1. Unity 报告两种情况的帧速率相同,即使对于 FixedUpdate() 情况,实际帧速率(现实世界每秒的帧数)显然要低得多。

  2. 除了速度变慢之外,碰撞检测和物理模拟逻辑似乎一切正常。应该碰撞的物体仍然碰撞;加速、施力等仍然有效。未在 20 毫秒(Unity 的毫秒)内跳过碰撞器的刚体仍然会像往常一样碰撞并弹回。

  3. Project 设置中的Maximum Allowed Timestep 选项定义了必须绘制帧之前的最大数量(Unity 的模拟时间)(我以前不知道它是干什么用的)。澄清:如果我将它设置为 0.5 秒,那么无论我在两个函数中放入多少代码,逻辑更新步骤 (Update()) 都会在 FixedUpdate() 轮模拟 0.5- th秒,然后渲染场景。