How to understand this Unity Coroutine?
using UnityEngine;
using System.Collections;
public class CoroutineExample : MonoBehaviour
{
IEnumerator Start ()
{
print ("Starting " + Time.time);
yield return StartCoroutine (WaitAndPrint ());
print ("Done " + Time.time);
}
IEnumerator WaitAndPrint ()
{
yield return new WaitForSeconds (5f);
print ("WaitAndPrint " + Time.time);
}
}
The result is
Starting 0
WaitAndPrint 5.010554
Done 5.010554
I have two questions?
First, How to understand the return value of function Start(). I used to see the return value of Start() is void. And in my view, Start() only executes once (one frame) by Unity, but yield return seems make Start() function execute in two frames;
Second, I am also confused by the result. I think the result should be
Starting 0
Done 5.010554
WaitAndPrint 5.010554
Because StartCoroutine() starts the function WaitAndPrint(). In function WaitAndPrint(), yield return makes this function pause in this frame and return to Start(). Then Start() continues going on and prints "Done xxxxx". After 5 seconds, WaitAndPrint() resume and prints "WaitAndPrint xxxxx".
Where am I wrong?
When you call yield return
the control is taken by Unity.
When you start a Coroutine
Unity will take the IEnumerator
returned by the method and will call MoveNext on the IEnumerator
returned.
Based on the type of object and on the values in the object Unity will decide what to do.
In you case in the Start
method the yield
statement return another IEnumerator
so Unity will not call MoveNext
on the Start
returned object until the second IEnumerator
finishes.
In WaitAndPrint
the first MoveNext
returns a WaitForSeconds
object, based on that Unity decides that it will not call MoveNext
on in until 5 seconds have passed. After 5 seconds it calls MoveNext
again and the rest of the method is executed, which is just this line
print ("WaitAndPrint" + Time.time);
As the IEnumerator
returned by yield return StartCoroutine (WaitAndPrint ());
reached its end it will call MoveNext
on the IEnumerator
that was returned by Start
, this in turn will execute what ever is left of Start
:
print ("Done " + Time.time);
Hope this is clear enough :)
Here's how I understand this result :
The Start() function is called once by Unity and prints "Started".
Then the following line does two things :
yield return StartCoroutine (WaitAndPrint ());
The WaitAndPrint() coroutine will do its stuff :
Then the Start() coroutine will resume and print "Done" + time.
This is why
print ("WaitAndPrint" + Time.time);
is printed before :
print ("Done " + Time.time);
Also, you should edit your post, it misses a space in the first result :
WaitAndPrint5.010554
Should be
WaitAndPrint 5.010554
Sorry if it's not clear, it's my first time answering on StackOverflow, hope it helped !
IEnumerators
are iterator blocks, they dont necessarily execute for 1 frame, when you put a yield return
, you essentially are telling it to iterate over multiple frames.
When a yield return statement is reached in the iterator method, expression is returned, and the current location in code is retained.
上一篇: 嵌套协程生成的代码是什么
下一篇: 如何理解这个Unity协程?