【问题标题】:What is the consequence of doing heavy work in fixedUpdate()?在 fixedUpdate() 中做繁重的工作会有什么后果?
【发布时间】:2017-02-16 12:16:32
【问题描述】:

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

它会导致 Unity 的物理引擎混乱,还是会导致程序崩溃?

【问题讨论】:

  • 一些很好的答案 herehere
  • @DeclanPossnett 换句话说,如果我有一个 20 毫秒的默认 fixedTimeFrame 并且我的 fixedUpdate() 需要 100 毫秒来运行,那么游戏世界的移动速度将比它应该的慢 5 倍?
  • 基本上,this unity question 上的 最佳 答案解释说,您通常会在 Unity 中自然地获得每帧所需的物理更新量 - 但如果您施加如此大的负载在物理引擎上它实际上不会赶上帧速率,因此无法模拟!

标签: unity3d unity5 unity3d-2dtools


【解决方案1】:

答案和 cmets 非常有帮助,但它们对我的问题缺乏明确、翔实的答案。每个人都知道当你在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 秒后立即调用,并且然后将渲染场景。

【讨论】:

    【解决方案2】:

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

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

    基本上,在不降低性能的情况下,每帧可以运行多少代码是有限制的。聪明的重写应该使这变得不必要。看看您是否可以缓存计算结果或尽可能多地预先计算游戏之外的数据。

    【讨论】:

      猜你喜欢
      • 2021-09-05
      • 1970-01-01
      • 1970-01-01
      • 2014-04-18
      • 2016-05-18
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 2012-04-28
      相关资源
      最近更新 更多