在 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
系统的功能都会像整个世界都变慢一样。
还有:
Unity 报告两种情况的帧速率相同,即使对于 FixedUpdate()
情况,实际帧速率(现实世界每秒的帧数)显然要低得多。
除了速度变慢之外,碰撞检测和物理模拟逻辑似乎一切正常。应该碰撞的物体仍然碰撞;加速、施力等仍然有效。未在 20 毫秒(Unity 的毫秒)内跳过碰撞器的刚体仍然会像往常一样碰撞并弹回。
Project 设置中的Maximum Allowed Timestep
选项定义了必须绘制帧之前的最大数量(Unity 的模拟时间)(我以前不知道它是干什么用的)。澄清:如果我将它设置为 0.5 秒,那么无论我在两个函数中放入多少代码,逻辑更新步骤 (Update()
) 都会在 FixedUpdate()
轮模拟 0.5- th秒,然后渲染场景。
我知道如果我在 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
系统的功能都会像整个世界都变慢一样。
还有:
Unity 报告两种情况的帧速率相同,即使对于
FixedUpdate()
情况,实际帧速率(现实世界每秒的帧数)显然要低得多。除了速度变慢之外,碰撞检测和物理模拟逻辑似乎一切正常。应该碰撞的物体仍然碰撞;加速、施力等仍然有效。未在 20 毫秒(Unity 的毫秒)内跳过碰撞器的刚体仍然会像往常一样碰撞并弹回。
Project 设置中的
Maximum Allowed Timestep
选项定义了必须绘制帧之前的最大数量(Unity 的模拟时间)(我以前不知道它是干什么用的)。澄清:如果我将它设置为 0.5 秒,那么无论我在两个函数中放入多少代码,逻辑更新步骤 (Update()
) 都会在FixedUpdate()
轮模拟 0.5- th秒,然后渲染场景。