了解协程的执行
我在Unity工作,但这真的只是一个C#问题,所以我希望这是张贴这个的正确部分。 无论如何,我仍然无法想象我头脑中的脚本执行情况,特别是当有多个运行并且它们都具有不同的功能时。
最近变得更加复杂了,因为我已将Update,FixedUpdate和Coroutine添加到“When when this running”列表中了吗? 更新和固定更新我明白了。
至于Coroutine,我基本上明白这是一种功能,可以更精确地控制时序。 这是我知道我可以做的唯一方法:“返回新的WaitForSeconds(i);”
我的问题更多的是关于他们的执行顺序。 例如,如果我从更新(每帧运行一次)调用协同程序并且协程的等待时间为10(10),那么将暂停执行所有脚本? 有没有像一个中央时钟运行的一切? 更新不会再次运行,直到等待结束? 如果我有另一个包含不同协同程序的更新函数的脚本,并且两者都在同一时间运行,该怎么办?
也许我会模糊。 很难解释。 我已经在网上阅读了一些有关协程的信息,但没有一个真正以我可以想象的方式解释它。
你需要知道的第一件事是使用yield
关键字并返回一个IEnumerable
的函数变成迭代器。 它是编写实现IEnumerator
的类的语法糖。
它们通常与foreach
循环一起使用:
IEnumerable<string> GetFruits()
{
yield return "Apple";
yield return "Pear";
}
foreach (string fruit in GetFruits())
Console.WriteLine(fruit);
这里发生的事情是GetFruits
返回一个实现IEnumerator<string>
的生成器对象。 它的MoveNext
方法每次MoveNext
运行原始GetFruits
代码的一部分。 每次调用执行代码到下一个yield
的语句,并使用的“返回值” yield
设定Current
发生器的性能。
foreach
循环产生调用MoveNext
并将Current
存储到循环变量中的代码,这使得迭代更加可读,如下所示:
IEnumerator<string> fruitsGenerator = GetFruits().GetEnumerator();
while (fruitsGenerator.MoveNext())
{
string fruit = fruitsGenerator.Current;
Console.WriteLine(fruit);
}
但是你不限于在循环中使用迭代器。 您可以存储对生成器的引用并调用其MoveNext
方法,例如每秒一次。 或者每当用户按下按钮。 或者您可以使用Current
值来确定何时应该再次MoveNext
。
这正是Unity正在做的。 协程本质上是一个生成器对象(带有一些额外的信息,比如剩下多少时间,直到它再次被调用)。 当协程产生WaitForSeconds
对象时,Unity会更新该协程的等待时间,并且不会再次调用该协程的MoveNext
方法,直到等待时间结束。
除非协程仍处于“等待”状态,否则Unity的每个“更新周期”都会在您的协同程序上MoveNext
游戏对象和MoveNext
上的Update
。 正在等待的协程简单地被跳过 - 它不会阻塞任何其他代码。