Amb*_*ier 2 c# coroutine unity-game-engine async-await .net-4.6
yield return null;
在异步方法中,Coroutine(在Update运行每帧)的等效项是什么?
我找到的最接近的是await Task.Delay(1);
,但不要每帧都运行一次。
private IEnumerator RunEachFrame()
{
while (true)
{
print("Run Each frame right before rendering");
yield return null;
}
}
async void DoNotRunEachFrame()
{
while (true)
{
await Task.Delay(1); // What is the equivalent of yield return null here ?
}
}
Run Code Online (Sandbox Code Playgroud)
至少在 Unity 2018 中,您可以使用await Task.Yield()
. 例如:
using System.Threading.Tasks;
using UnityEngine;
public class AsyncYieldTest : MonoBehaviour
{
async void Start()
{
await Function();
}
async Task Function() {
while (gameObject != null)
{
await Task.Yield();
Debug.Log("Frame: " + Time.frameCount);
}
}
}
Run Code Online (Sandbox Code Playgroud)
会给你输出:
Frame: 1
Frame: 2
Frame: 3
...
Run Code Online (Sandbox Code Playgroud)
似乎如果该Debug.Log("Frame: " + Time.frameCount);
行在 之前await Task.Yield();
,它将在第一帧中运行两次。我不确定这是什么原因。
随着UniTask库的UniTask.NextFrame
很可能获得匹配的行为yield return null
完全让你不与第一门框上获得2个消息
using Cysharp.Threading.Tasks;
using UnityEngine;
public class AsyncYieldTest : MonoBehaviour
{
async void Start()
{
await Function();
}
async UniTask Function() {
while (gameObject != null)
{
// Debug.Log first like with yield return null
Debug.Log("Frame: " + Time.frameCount);
await UniTask.NextFrame();
}
}
}
Run Code Online (Sandbox Code Playgroud)
目前没有 for的等效方法yield return null
。
我要说这是不可能的,因为异步可以在Thread
除主Thread
线程之外的其他线程中调用,因为您不能在另一个线程中使用Unity的API,但是看起来 Unity通过在中实现自己的异步上下文来解决了线程问题Unity 5.6.0b5及更高版本。
仍然可以这样做,但是您必须自己实现或使用现有的API。该UnityAsync
API已经可以做到这一点。你可以在这里得到。该NextUpdate
功能代替yield return null
指令。
例子:
您通常的协程代码:
private IEnumerator RunEachFrame()
{
while (true)
{
print("Run Each frame right before rendering");
yield return null;
}
}
Run Code Online (Sandbox Code Playgroud)
等效的异步代码:
using UnityAsync;
using System.Threading.Tasks;
public class UpdateLoop : AsyncBehaviour
{
void Start()
{
RunEachFrame();
}
// IEnumerator replaced with async void
async void RunEachFrame()
{
while(true)
{
print("Run Each frame right before rendering");
//yield return null replaced with await NextUpdate()
await NextUpdate();
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,脚本是如何继承AsyncBehaviour
而不是的MonoBehaviour
。
如果您确实要继承MonoBehaviour
而不是AsyncBehaviour
API并仍然使用此API,请NextUpdate
直接以调用该函数。以下Await.NextUpdate()
是一个完整的等效示例:
using UnityAsync;
using System.Threading.Tasks;
public class UpdateLoop : MonoBehaviour
{
async void Start()
{
await RunEachFrame();
}
async Task RunEachFrame()
{
while(true)
{
print("Run Each frame right before rendering");
await Await.NextUpdate(); // equivalent of AsyncBehaviour's NextUpdate
}
}
}
Run Code Online (Sandbox Code Playgroud)
以下是完整的受支持的等待功能:
NextUpdate
NextLateUpdate
NextFixedUpdate
Updates(int framesToWait)
LateUpdates(int framesToWait)
FixedUpdates(int stepsToWait)
Seconds(float secondsToWait)
SecondsUnscaled(float secondsToWait)
Until(Func<bool> condition)
While(Func<bool> condition)
Custom(CustomYieldInstruction instruction)
AsyncOp(AsyncOperation op)
所有这些都可以在Await
类中找到,以防万一它们被重命名或删除。
如果您在使用此API时遇到问题,请参阅Unity 专门针对该API的论坛帖子,并在那里提问。