具有“产量”的function如何正常工作?

我得到了这个方法(在Unity C#Script中),但我不明白“yield”部分是如何工作的。

我从MSDN中知道该函数将返回一个我可以迭代的IEnumerator,但是这段代码等待1.5秒并且没有迭代,因为这意味着,内部创建的对象被多次创建。 这里的任何人都可以解释一下这段代码的工作原理

IEnumerator DestroyShip() { // create new gameobject Instantiate(ExplosionPrefab, transform.position, transform.rotation); // make current gameobject invisible gameObject.renderer.enabled = false; // set new position for the current gameobject transform.position = new Vector3(0f, transform.position.y, transform.position.z); // wait for 1,5 seconds yield return new WaitForSeconds(1.5f); // make the current gameobject visible again gameObject.renderer.enabled = true; } 

编译器为您生成的枚举器正在迭代。 一旦。

编译器将生成一个实现IEnumerator的类,该类具有MoveNext()函数和Current属性。 该类将具有在调用之间存储函数状态所需的所有成员。 具体细节可以被视为“编译器魔术”。

这个生成的类的对象将由Unity3d引擎处理和管理。 Unity3d引擎将在每个帧上调用每个活动协程上的MoveNext()(除非另有说明)。

这使Unity3d Programmer能够编写一次一帧播放的脚本。 C#编译器魔术和Unity3d引擎魔术的结合使得脚本function非常强大但易于使用。

要回答你的问题:你的函数中的代码将被执行一次,但它会在’yield return’语句中暂停。

如上所述,实现IEnumerator的特殊对象是由C#编译器创建的。

在第一次调用MoveNext()时,您的函数会创建爆炸并将当前对象设置为“new WaitForSeconds(1.5f)”。

Unity3d引擎检查此对象,看到它是特殊类“WaitForSeconds”的实例,因此将枚举器放在某个等待队列上,并且在1.5秒之前不会要求第二个元素。 与此同时,将渲染许多帧并播放爆炸。

1.5秒后,Unity将从队列中抓取枚举器,并再次调用MoveNext()。 函数的第二部分现在将执行,但无法生成第二个对象。 MoveNext()将返回false以指示它无法获取新元素,这是Unity3d将此枚举器抛弃的信号。 垃圾收集器将在某个时间点回收内存。

如上所述:许多编译器和Unity3d魔术正在进行中。 只要你记得你的函数将被保留到每个yield return语句的下一帧,你就会知道这些特殊函数会受益。

如果yield使用一次,就好像你返回一个带有一个元素的IEnumerator,这就是为什么你会得到它不会迭代的印象。

这是yield关键字的一个相当奇怪的用法,很难理解为什么它被实现,所以没有看到整个上下文。

最好返回IEnumerable而不是IEnumerator因为它更易灵活且易于使用。 使用IEnumerable更好。 yield return只是用于实现迭代器块的语法糖,编译器生成相关代码,因为它本质上是标准的boater板,可以通过编程方式轻松生成。 当你想要将一系列单个动作apear作为集合时,通常使用yield return,例如:

 public IEnumerable GetThings() { yield return GetNextThing(); }