c# - 这个带有 "yield"的函数如何详细工作?

标签 c# unity3d yield yield-return

我得到了这个方法(在 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/

相关文章:

c# - 序列化使用 yield return 创建的 IEnumerator<T>

c# - ASP.net MVC 4 显示图像

c# - 使用 NAudio 播放带有自定义编解码器的 WAV

c# - 摆脱临时文件夹中的 Crystal Report 生成的文件 - Visual Studio 2008

c# - 如何访问父表单?

c# - 我如何以最好的方式告诉主导 x 或 y 方向?

macos - Mac OSX,Apple 拒绝了 Unity 应用程序。协同设计问题?

python - 递归斐波那契 yield

c# - 如何将存储的MP3文件数据(byte [])转换为float [] Unity可以用作AudioSource-Data?

python - 有没有办法计算我在 yield 中有多少个值?