理解协同程序的执行

时间:2015-04-13 12:15:12

标签: c# unity3d

我在Unity工作,但这只是一个C#问题,所以我希望这是发布这个问题的正确部分。无论如何,我仍然无法在脑中看到脚本的执行,特别是当有多个运行时它们都有不同的功能。

最近因为我已经将Update,FixedUpdate和Coroutine添加到我的“何时运行”列表中而变得更加复杂?更新和修复更新我得到了要点。

至于Coroutine,我基本上理解它是一种功能,可以让我更准确地控制时间。这是我知道我能做的唯一方法“收益返回新的WaitForSeconds(i);”

我的问题更多是关于他们的执行顺序。例如,如果我从更新调用协程(每帧运行一次)并且协程有一个waitforseconds(10),那么将暂停执行所有脚本?是否有一个中央时钟运行一切?在等待结束之前,更新是否会再次运行?如果我有另一个脚本,其中包含一个包含不同协程的更新函数,并且两个协同程序同时运行,该怎么办?

也许我是模糊的。难以解释。我已经在网上阅读了一些关于协同程序的信息,但没有任何东西可以用我可以想象的方式来解释它。

1 个答案:

答案 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; ;州。正在等待的协程只是被跳过 - 它不会阻止任何其他代码。