Unity3D - 使用 Time.deltaTime 作为协程的等待时间
Unity3D - Using Time.deltaTime as wait time for a coroutine
TL,DR: 在协程中使用 Time.deltaTime 作为 yield 的等待时间安全吗?
通常为了避免 Update() 内部不必要的逻辑以实现短暂的功能,我会 运行 一个协程。例如,在我的游戏中,我有一个慢速协程,它定期检查 NPC 和玩家之间的距离,如果该距离低于某个阈值,我将 运行 一个更频繁的协程,使用光线投射进行更昂贵的视线测试等等。这似乎比在 Update() 中不断检查所有内容更有效。
我的问题是:使用 Time.deltaTime 作为 yield 的等待时间,从而在协程期间模拟 Update() 是否安全?即 yield return new WaitForSeconds(Time.deltaTime);
由于 deltaTime 不是常量,如果下一帧花费的时间比上一帧长,会发生什么情况 - 协程是否延迟到下一帧,或者是否发生了可怕的事情,比如整个帧都被延迟到协程完成?我很想允许一个安全缓冲区,例如yield return new WaitForSeconds(Time.deltaTime * 1.2f);
但理想情况下,我希望它能够精确地执行每一帧。
is it safe to use Time.deltaTime as the wait time for the yield in a
coroutine?
否。那不是如何使用 WaitForSeconds
函数。 WaitForSeconds
以秒为单位作为参数,而不是 Time.deltaTime
在每一帧中提供的微小值。
下面是如何使用 WaitForSeconds
函数的示例。
IEnumerator waitFunction1()
{
Debug.Log("Hello Before Waiting");
yield return new WaitForSeconds(3); //Will wait for 3 seconds then run the code below
Debug.Log("Hello After waiting for 3 seconds");
}
至于使用 Time.deltaTime
等待,除了另一个 float
变量之外,您通常在 while
循环中使用它 increment
或 decrement
until you reach the wanted value.The 使用 Time.deltaTime
的好处是你可以在等待时看到还剩多少等待时间。您可以将其用于倒计时或倒计时。您还将 yield return null;
放在 while
循环中,这样 Unity 将允许其他脚本也 运行 并且您的应用程序不会冻结。下面是如何使用 Time.deltaTime
等待 3 秒的示例。您可以轻松地将其变成倒数计时器。
IEnumerator waitFunction2()
{
const float waitTime = 3f;
float counter = 0f;
Debug.Log("Hello Before Waiting");
while (counter < waitTime)
{
Debug.Log("Current WaitTime: " + counter);
counter += Time.deltaTime;
yield return null; //Don't freeze Unity
}
Debug.Log("Hello After waiting for 3 seconds");
}
如果你想检查每一帧有WaitForEndOfFrame
如果您不需要特定的等待时间,WaitForSeconds 就没有意义
您也可以yield return www
等待它完成
更新,有CustomYieldInstruction和一些继承用于协程,比如WaitUntil
我知道这有点旧,但我今天在寻找相关内容时偶然发现了它。
无论如何,程序员的回答是一个好的开始。使用 Time.detlaTime 不是释放协程控制的好方法。首先,使用空值将使您进入模拟的下一帧。其次,如果您刚完成的帧有点慢(或下一帧有点快)会发生什么情况。请记住,模拟(或游戏)是按帧运行的,就像电影中的帧一样。因此,使用 WaitForSeconds 可以产生一些有趣的效果。例如,如果您请求的时间发生在帧之间,您认为会发生什么?协程将在 请求的时间后重新获得控制权。因此,如果您希望在协程中的每个循环中只执行 WaitForSeconds(Time.deltaTime),那么您很可能会跳过偶尔的帧(有时更多)。
我有一个同事在一个很长的 运行 协同程序中做了一堆 WaitForSeconds,总时间比预期长 5 到 10 秒。请求时间内帧错误的一部分会累加起来,并且与自然界不同,在自然界中错误往往会被平均掉,这些错误总是会增加 up。那是因为流逝的时间总是大于或等于请求的时间。
程序员的回答告诉你如何使用Time.deltaTime来获取模拟时间的流逝。我应该警告你,一旦你开始使用 null 以外的东西来释放协程的控制权,Time.deltaTime 可能会停止为你工作。
如果您使用 null 后跟一些代码后跟 WaitForEndFrame,当协同程序恢复控制时,您仍将处于同一帧内。因为你和调用WaitForEndFrame之前还在同一帧,所以经过的模拟时间会为零,但是Time.deltaTime不会为零。所以,是的,一旦开始混合不同的 return 类型,测量时间就会变得棘手。您还应该小心在框架和固定框架之间切换。使用 WaitForFixedUpdate 将使您进入固定帧的时代。在 WaitForFixedUdpate 之后调用 Time.fixedDeltaTime 将为您提供该固定帧和前一个固定帧之间的时间,这与 Time.deltaTime 或帧的任何计时无关。
TL,DR: 在协程中使用 Time.deltaTime 作为 yield 的等待时间安全吗?
通常为了避免 Update() 内部不必要的逻辑以实现短暂的功能,我会 运行 一个协程。例如,在我的游戏中,我有一个慢速协程,它定期检查 NPC 和玩家之间的距离,如果该距离低于某个阈值,我将 运行 一个更频繁的协程,使用光线投射进行更昂贵的视线测试等等。这似乎比在 Update() 中不断检查所有内容更有效。
我的问题是:使用 Time.deltaTime 作为 yield 的等待时间,从而在协程期间模拟 Update() 是否安全?即 yield return new WaitForSeconds(Time.deltaTime);
由于 deltaTime 不是常量,如果下一帧花费的时间比上一帧长,会发生什么情况 - 协程是否延迟到下一帧,或者是否发生了可怕的事情,比如整个帧都被延迟到协程完成?我很想允许一个安全缓冲区,例如yield return new WaitForSeconds(Time.deltaTime * 1.2f);
但理想情况下,我希望它能够精确地执行每一帧。
is it safe to use Time.deltaTime as the wait time for the yield in a coroutine?
否。那不是如何使用 WaitForSeconds
函数。 WaitForSeconds
以秒为单位作为参数,而不是 Time.deltaTime
在每一帧中提供的微小值。
下面是如何使用 WaitForSeconds
函数的示例。
IEnumerator waitFunction1()
{
Debug.Log("Hello Before Waiting");
yield return new WaitForSeconds(3); //Will wait for 3 seconds then run the code below
Debug.Log("Hello After waiting for 3 seconds");
}
至于使用 Time.deltaTime
等待,除了另一个 float
变量之外,您通常在 while
循环中使用它 increment
或 decrement
until you reach the wanted value.The 使用 Time.deltaTime
的好处是你可以在等待时看到还剩多少等待时间。您可以将其用于倒计时或倒计时。您还将 yield return null;
放在 while
循环中,这样 Unity 将允许其他脚本也 运行 并且您的应用程序不会冻结。下面是如何使用 Time.deltaTime
等待 3 秒的示例。您可以轻松地将其变成倒数计时器。
IEnumerator waitFunction2()
{
const float waitTime = 3f;
float counter = 0f;
Debug.Log("Hello Before Waiting");
while (counter < waitTime)
{
Debug.Log("Current WaitTime: " + counter);
counter += Time.deltaTime;
yield return null; //Don't freeze Unity
}
Debug.Log("Hello After waiting for 3 seconds");
}
如果你想检查每一帧有WaitForEndOfFrame
如果您不需要特定的等待时间,WaitForSeconds 就没有意义
您也可以yield return www
等待它完成
更新,有CustomYieldInstruction和一些继承用于协程,比如WaitUntil
我知道这有点旧,但我今天在寻找相关内容时偶然发现了它。
无论如何,程序员的回答是一个好的开始。使用 Time.detlaTime 不是释放协程控制的好方法。首先,使用空值将使您进入模拟的下一帧。其次,如果您刚完成的帧有点慢(或下一帧有点快)会发生什么情况。请记住,模拟(或游戏)是按帧运行的,就像电影中的帧一样。因此,使用 WaitForSeconds 可以产生一些有趣的效果。例如,如果您请求的时间发生在帧之间,您认为会发生什么?协程将在 请求的时间后重新获得控制权。因此,如果您希望在协程中的每个循环中只执行 WaitForSeconds(Time.deltaTime),那么您很可能会跳过偶尔的帧(有时更多)。
我有一个同事在一个很长的 运行 协同程序中做了一堆 WaitForSeconds,总时间比预期长 5 到 10 秒。请求时间内帧错误的一部分会累加起来,并且与自然界不同,在自然界中错误往往会被平均掉,这些错误总是会增加 up。那是因为流逝的时间总是大于或等于请求的时间。
程序员的回答告诉你如何使用Time.deltaTime来获取模拟时间的流逝。我应该警告你,一旦你开始使用 null 以外的东西来释放协程的控制权,Time.deltaTime 可能会停止为你工作。
如果您使用 null 后跟一些代码后跟 WaitForEndFrame,当协同程序恢复控制时,您仍将处于同一帧内。因为你和调用WaitForEndFrame之前还在同一帧,所以经过的模拟时间会为零,但是Time.deltaTime不会为零。所以,是的,一旦开始混合不同的 return 类型,测量时间就会变得棘手。您还应该小心在框架和固定框架之间切换。使用 WaitForFixedUpdate 将使您进入固定帧的时代。在 WaitForFixedUdpate 之后调用 Time.fixedDeltaTime 将为您提供该固定帧和前一个固定帧之间的时间,这与 Time.deltaTime 或帧的任何计时无关。