理解协同程序的执行

Mas*_*ous 3 c# unity-game-engine

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

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

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

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

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

Pie*_*oet 8

您需要知道的第一件事是使用yield关键字并返回an的函数IEnumerable将转换为迭代器.它是编写实现类的语法糖IEnumerator.

它们通常与foreach循环一起使用:

IEnumerable<string> GetFruits()
{
    yield return "Apple";
    yield return "Pear";
}

foreach (string fruit in GetFruits())
    Console.WriteLine(fruit);
Run Code Online (Sandbox Code Playgroud)

这里发生的是GetFruits返回一个实现的生成器对象IEnumerator<string>.它的MoveNext方法在GetFruits每次调用时都会运行原始代码的一部分.每个调用执行代码直到下一个yield语句,并使用它的'返回值' yield来设置Current生成器的属性.

foreach循环的结果在调用代码MoveNext和存储Current到循环变量,这使得迭代更加易读,类似如下:

IEnumerator<string> fruitsGenerator = GetFruits().GetEnumerator();
while (fruitsGenerator.MoveNext())
{
    string fruit = fruitsGenerator.Current;
    Console.WriteLine(fruit);
}
Run Code Online (Sandbox Code Playgroud)

但是你不仅限于在循环中使用迭代器.您可以存储对生成器的引用并调用其MoveNext方法,例如,每秒调用一次.或者每当用户按下按钮时.或者您可以使用该Current值来确定何时MoveNext应再次调用.

这正是Unity正在做的事情.协程本质上是一个生成器对象(带有一些额外的信息,例如在它应该被再次调用之前剩余多少时间).当协程生成一个WaitForSeconds对象时,Unity会更新该协程的MoveNext等待时间,并且在等待时间结束之前不会再次调用该协程的方法.

除非协程仍处于"等待"状态,否则Unity会Update在每个"更新周期"中调用游戏对象和MoveNext协程.正在等待的协程只是被跳过 - 它不会阻止任何其他代码.