Zen*_* Qu 22 c# coroutine unity-game-engine
关于协同程序(在Unity3D和其他地方)如何工作,我感到困惑和好奇.coroutine是新线程吗?他们说Unity的文档:
协程是一个可以暂停执行(yield)直到给定的YieldInstruction完成的函数.
他们在这里有C#示例:
using UnityEngine;
using System.Collections;
public class example : MonoBehaviour {
void Start() {
print("Starting " + Time.time);
StartCoroutine(WaitAndPrint(2.0F));
print("Before WaitAndPrint Finishes " + Time.time);
}
IEnumerator WaitAndPrint(float waitTime) {
yield return new WaitForSeconds(waitTime);
print("WaitAndPrint " + Time.time);
}
}
Run Code Online (Sandbox Code Playgroud)
我对这个例子有很多疑问:
在上面的例子中,哪一行是协程?是WaitAndPrint()一个协程?是WaitForSeconds()一个协程?
在这一行:yield return new WaitForSeconds(waitTime);为什么都yield和return存在?我在Unity文档中读到"yield语句是一种特殊的返回,它确保函数将在下次调用yield语句后继续执行." 如果yield是特别的return,return这里做了什么?
为什么我们要退货IEnumerator?
是否StartCoroutine开始新线程?
WaitAndPrint()在上面的例子中被调用了多少次?难道yield return new WaitForSeconds(waitTime);真的回来了?如果是,那么我猜WaitAndPrint()在上面的代码中被调用了两次.我想StartCoroutine()是WaitAndPrint()多次打电话.但是,我看到另一个Unity文档说:"可以使用yield语句在任何时候暂停执行协程.yield return value指定何时恢复协程." 这些话让我觉得WaitAndPrint()实际上还没有回来; 它只是暂停了; 它正等着WaitForSeconds()回来.如果是这种情况,那么在上面的代码WaitAndPrint()中只调用一次,并且StartCoroutine只负责启动该函数,而不是多次调用它.
spe*_*der 21
协同程序是一种非常强大的技术,用于模拟.net4.5中async/await支持的各种功能,但在早期版本中(c#> = v2.0).
Microsoft CCR(读取)也采用(使用?)这种方法.
让我们放开一件事.yield单独无效,并且始终跟随return或break.
想想标准的IEnumerator(它不会产生流控制消息).
IEnumerator YieldMeSomeStuff()
{
yield "hello";
Console.WriteLine("foo!");
yield "world";
}
Run Code Online (Sandbox Code Playgroud)
现在:
IEnumerator e = YieldMeSomeStuff();
while(e.MoveNext())
{
Console.WriteLine(e.Current);
}
Run Code Online (Sandbox Code Playgroud)
什么输出?
hello foo! world
请注意MoveNext,在枚举器产生"世界"之前,我们第二次调用时,在枚举器中运行了一些代码.这意味着在枚举器中,我们可以编写执行代码直到它命中一个yield return语句,然后简单地暂停直到有人调用MoveNext(方便地使用整齐捕获的所有状态/变量,这样我们就可以在我们离开的地方继续执行).经过一个MoveNext电话,代码之后的下一位yield return发言可以运行,直到另一个yield return到达.因此,我们现在可以yield return通过MoveNext调用Enumerator来控制语句之间的代码执行.
现在,我们的枚举器不会产生字符串,而是会产生一条消息,告诉来电者MoveNext,"请MoveNext再次呼叫前等待x(等待时间)秒".写入调用者是为了"理解"各种消息.这些消息将始终沿着"请等待MoveNext再次呼叫之前发生这样的事情".
现在我们有一个强大的暂停和重新启动代码的方法,它需要满足其他条件才能继续,而不必将该功能写入另一个方法,比如在没有协同程序的情况下执行异步操作.如果没有协同程序,你就会强行传递一个可怕的异步状态对象,你需要手动组装以捕获一个方法结束和另一个异步之后的另一个方法的启动之间的状态.协同程序消除了这种情况,因为范围被保留(通过编译器魔术),因此您的本地变量会持久存在于长期存在的异步内容中.
StartCoroutine只需启动整个过程.它调用MoveNextEnumerator ...一些代码在枚举器中运行...枚举器产生一个控制消息,通知代码StartCoroutine何时MoveNext再次调用.这不需要在新的Thread中发生,但在多线程场景中可以很方便,因为我们可以MoveNext从不同的线程调用并控制工作的完成位置.
| 归档时间: |
|
| 查看次数: |
15051 次 |
| 最近记录: |