我得到了这个方法(在 Unity C# 脚本中),但我不明白“ 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 程序员能够编写一次播放一帧的脚本。 C# 编译器魔法和 Unity3d 引擎魔法的结合产生了非常强大但易于使用的脚本。
回答您的问题:函数中的代码将执行一次,但会在“yield return”语句处暂停。
如上所述,C# 编译器创建了一个实现 IEnumerator 的特殊对象。
在第一次调用 MoveNext() 时,您的函数会创建一个爆炸并将当前对象设置为“new WaitForSeconds(1.5f)”。
Unity3d 引擎检查此对象,发现它是特殊类“WaitForSeconds”的一个实例,因此将枚举器放在某个等待队列中,并且在 1.5 秒过去之前不会请求第二个元素。在此期间,将渲染许多帧并播放爆炸。
1.5 秒后,Unity 将从队列中获取枚举器,并再次调用 MoveNext()。您的函数的第二部分现在将执行,但将无法生成第二个对象。 MoveNext() 将返回 false 以指示它未能获取新元素,这是向 Unity3d 发出的信号,以丢弃此枚举器。垃圾收集器会在某个时间点回收内存。
如前所述:许多编译器和 Unity3d 魔法正在发生。只要您记得您的函数将在每个 yield return 语句中被搁置到下一帧,您就会充分了解如何从这些特殊函数中获益。
关于c# - 这个带有 "yield"的函数如何详细工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3438670/