Understanding The Execution of Coroutines

大憨熊 提交于 2021-01-27 14:52:58

问题


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.

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);"

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.


回答1:


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.

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);

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.

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);
}

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.

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.

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.



来源:https://stackoverflow.com/questions/29605067/understanding-the-execution-of-coroutines

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!