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 ());
  • it starts the WaitAndPrint() coroutine
  • it waits for it to be over before continuing in the Start() coroutine.
  • The WaitAndPrint() coroutine will do its stuff :

  • Wait for 5 seconds
  • Print "WaitAndPrint" + time
  • 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.

  • https://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx
  • 链接地址: http://www.djcxy.com/p/53170.html

    上一篇: 嵌套协程生成的代码是什么

    下一篇: 如何理解这个Unity协程?