理解协程的执行 [英] Understanding The Execution of Coroutines

查看:33
本文介绍了理解协程的执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Unity 工作,但这实际上只是一个 C# 问题,所以我希望这是发布此内容的正确部分.无论如何,我仍然无法在脑海中想象脚本的执行情况,尤其是当有多个运行并且它们都有不同的功能时.

I'm working in Unity, but this is really just a C# question so I hope this is the right section to post this. Anyways, I still have trouble visualizing the execution of scripts in my head, especially when there are more than one running and they all have different functions.

最近变得更复杂了,因为我在何时运行"列表中添加了更新、固定更新和协程?更新和固定更新我明白了.

It's gotten more complicated recently as I've added Update, FixedUpdate, and Coroutine to my list of "When's this running"? Update and Fixed Update I get the gist.

对于协程,我基本上理解它是一种函数,可以让我更精确地控制时间.这是我知道我能做到的唯一方法收益率返回新的 WaitForSeconds(i);"

As for Coroutine, I basically understand it's a type of function that gives me a more precise control of timing. It's the only way I know I can do "yield return new WaitForSeconds(i);"

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

My question is more about their execution order. For example if I call a coroutine from update(which runs once per frame) and that coroutine has a waitforseconds(10), then will pause execution of all script? Is there like one central clock running everything? Will Update not run again until the wait is up? What if I've got another script with an update function containing a different coroutine waiting as well and both run at the same time?

也许我太含糊了.很难解释.我已经在网上阅读了几篇关于协程的信息,但没有什么能以我可以想象的方式真正解释它.

Maybe I'm being to vague. Hard to explain. I've read a couple of pieces of information online about coroutine, but nothing that really explains it in a way I can visualize it.

推荐答案

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

The first thing you need to know is that functions that use the yield keyword and return an IEnumerable are turned into iterators. It's syntactic sugar for writing a class that implements IEnumerator.

它们通常与 foreach 循环结合使用:

They're usually used in conjunction with foreach loops:

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

foreach (string fruit in GetFruits())
    Console.WriteLine(fruit);

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

What happens here is that GetFruits returns a generator object that implements IEnumerator<string>. Its MoveNext method runs part of the original GetFruits code each time it is called. Each call executes code up to the next yield statement, and uses the 'return value' of that yield to set the Current property of the generator.

foreach 循环导致代码调用 MoveNext 并将 Current 存储到循环变量中,这使得迭代更具可读性,某些东西像下面这样:

The foreach loop results in code that calls MoveNext and that stores Current into the loop variable, which makes iteration much more readable, something like the following:

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

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

But you're not limited to using iterators in loops. You can store a reference to a generator and call its MoveNext method, say, once per second. Or whenever a user presses a button. Or you could use the Current value to determine when MoveNext should be called again.

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

And that's exactly what Unity is doing. A coroutine is essentially a generator object (with some extra information, such as how much time is left until it should be called again). When a coroutine yields a WaitForSeconds object, Unity updates the waiting-time of that coroutine and will not call that coroutine's MoveNext method again until the waiting time is over.

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

Each 'update cycle', Unity calls Update on your game-objects and MoveNext on your coroutines, unless a coroutine is still in a 'waiting' state. A coroutine that's waiting is simply being skipped - it doesn't block any other code.

这篇关于理解协程的执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆