C# 中的 IEnumerator 是什么?它在 Unity 中有何用途?

I-a*_*r-9 5 c# unity-game-engine

最近看到一个在Unity中使用C#生成对象的教程。因为老师使用了这样的函数

   public IEnumerator CallSpawner()
   {
      yield return new WaitForSeconds(0.5f);
      SpawnObstacles();
   }
Run Code Online (Sandbox Code Playgroud)

我想问一下 IEnumerator 函数有什么用?我们不能通过这个过程来做到这一点吗

float diffTime = 0f;
private void Update()
{
    if(Time.time - diffTime == 0.5f)
    {
        diffTime = Time.time;
        SpawnObstacles();
    }
}
Run Code Online (Sandbox Code Playgroud)

我阅读了文档但无法理解它..

Cai*_*ard 8

IEnumerator 函数有什么用

IEnumerator没有函数,它是返回类型C# 也没有函数(但我知道你的意思)——在 C# 中我们称它们为方法

I Enumerator 如此称呼意味着它是一个接口,因此任何实现 IEnumerator 接口的类都可以通过此方法返回

在这种用法的实践中,它实际上更像是一种黑客行为,而不是旨在提供枚举器的真正意图,即逐步遍历(或生成)一组事物。

当您在方法中使用yield return语句时,“会发生一些神奇的事情”,它不是return经典意义上的 a,而是创建一个工具,使代码可以从它停止的地方恢复(调用返回的枚举器中的下一个项目将导致代码从yield之后恢复,并保留之前的所有状态,而不是重新开始)。

如果您查看 MSDN 的收益示例:

public class PowersOf2
{
    static void Main()
    {
        // Display powers of 2 up to the exponent of 8:
        foreach (int i in Power(2, 8))
        {
            Console.Write("{0} ", i);
        }
    }

    public static System.Collections.Generic.IEnumerable<int> Power(int number, int exponent)
    {
        int result = 1;

        for (int i = 0; i < exponent; i++)
        {
            result = result * number;
            yield return result;
        }
    }

    // Output: 2 4 8 16 32 64 128 256
}
Run Code Online (Sandbox Code Playgroud)

循环由 ; 控制i;如果这不是 ayield return那么这将无法按预期运行(它无法返回枚举器作为开始,但我们将忽略它)。假设它只是一个普通的return,循环根本就不会循环;代码将进入,启动循环,点击return,然后只返回一个数字,然后循环所在位置的所有内存都会被忘记。

通过将其设置为 a yield return,将返回一个枚举器,并设置一小组“已保存状态”,循环可以记住当前值i- 每次您询问下一个值时,代码都会从中断处恢复(即在产量之后),循环再次循环并产生不同的值。当然,这会持续到最大值..此时返回的枚举器表示它没有更多项目

你也可以永远产生。如果代码永远无法逃脱循环,那么它将永远产生/生成


在这种情况下,您必须使用 WaitForSeconds,yield return new WaitForSeconds因为这就是 WaitForSeconds 的工作原理。Yielding 将一个枚举器交给调用方法,然后调用方法可以自由地枚举它。从文档看来,这是故意在下一帧上完成的,因此使用yield(可能重复)是一种安排跨多个帧出现的代码块的方法,而无需某种外部状态管理来记住进程的位置罗嗦

  • 如果state = 1,则关上门并将state加1,
  • else if state = 2 则点燃火炬并加 1
  • 否则如果状态 = 3 ...”。

你可以只

  • 屈服,
  • 关门,
  • 屈服,
  • 点燃火炬,
  • 屈服 ..

我们不能通过这个过程来做到这一点吗

当然,看起来很合理;每秒看时钟 100 次,如果自你第一次看时钟以来已经过去了 0.5 秒,则生成障碍物

我想象(从未使用过 Unity;除了阅读该函数的文档之外,不自称了解任何有关它的内容)您的 Update 循环还有很多事情要做,因此将一个进程交给一个专门的“先等再做”比花所有时间看时钟并进行可能复杂的计算来确定是否应该做某事更有效;生活中大多数以每x毫秒轮询一次的方式开始的事情都受益于切换到“如果事件发生,就对其做出反应”的工作方式