我在Unity工作,但这只是一个C#问题,所以我希望这是发布这个问题的正确部分。无论如何,我仍然无法在脑中看到脚本的执行,特别是当有多个运行时它们都有不同的功能。
最近因为我已经将Update,FixedUpdate和Coroutine添加到我的“何时运行”列表中而变得更加复杂?更新和修复更新我得到了要点。
至于Coroutine,我基本上理解它是一种功能,可以让我更准确地控制时间。这是我知道我能做的唯一方法“收益返回新的WaitForSeconds(i);”
我的问题更多是关于他们的执行顺序。例如,如果我从更新调用协程(每帧运行一次)并且协程有一个waitforseconds(10),那么将暂停执行所有脚本?是否有一个中央时钟运行一切?在等待结束之前,更新是否会再次运行?如果我有另一个脚本,其中包含一个包含不同协程的更新函数,并且两个协同程序同时运行,该怎么办?
也许我是模糊的。难以解释。我已经在网上阅读了一些关于协同程序的信息,但没有任何东西可以用我可以想象的方式来解释它。
答案 0 :(得分:8)
您需要知道的第一件事是使用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
方法每次调用时都会运行原始GetFruits
代码的一部分。每次调用都会执行代码,直到下一个yield
语句,并使用&#39;返回值&#39;其中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会在您的游戏对象上调用Update
,在您的协程上调用MoveNext
,除非协程仍在等待&#39; ;州。正在等待的协程只是被跳过 - 它不会阻止任何其他代码。