question about Coroutines and waiting for a function to finish

Let’s say I have a function “f” that needs to wait until “g” is finished it’s execution, but “g” has multiple yield returns in it. Something like:

void f() {
  yield return StartCoroutine(g());
  // do something else now...
}
IEnumerator g() {

  // do something

  while (something)
    yield return null;

  // so something else

  yield return null;
}

So in this case, I don’t want f() to continue until the final “yield return null” has been called in g(). But my understanding is that f() will continue after the very first time “yield return null” has been called.

I suppose the while loop in g() could just be empty. That would be a fix. But is there ever a case where we need multiple “yield return null” statements in a function, but need to “wait” for the last one?

Thanks for any insights into this. I’ve read the following:

http://docs.unity3d.com/Documentation/ScriptReference/index.Coroutines_26_Yield.html

But I don’t find it to be the most helpful piece of documentation. It uses the statement: “The yield statement is a special kind of return, that ensures that the function will continue from the line after the yield statement next time it is called.” But that doesn’t make sense to me, because the function WILL continue whether or not it is called again!

Thanks.

If you yield return another coroutine like you did, it will wait until the coroutine is finished, but i guess you have trouble to understand what a coroutine is.

A coroutine is not a function that runs in some magic parallel thread. The yield statement is actually a C# feature. Functions that contain this statement have to return an IEnumerator. Such a function is called a generator-function. When you call the function it doesn’t execute any of the code in it. It just returns an object that implements the IEnumerator interface. This object can be used to execute the actual code until the next yield statement.

In Unity you pass the result of the generator to StartCoroutine. This function will store the given object internally on the MonoBehaviour instance and will take care of executing it.

The coroutine scheduler in Unity will drive the execution when it’s time to do so.

When you yield return in a coroutine, the coroutine is exited at this point and will return the given object to the scheduler. WaitForSeconds is just a class that holds a float value. The scheduler will check what the coroutine returns and “schedule” the coroutine for continue when it’s time to do so. When you yield another coroutine (a Coroutine is returned by StartCoroutine), the scheduler will suspend the execution until the yielded coroutine has finished.

So in your case the coroutines should look like this:

IEnumerator f() {
    Debug.Log("f() started");
    yield return StartCoroutine(g());
    Debug.Log("f() is done");
}

IEnumerator g() {
    Debug.Log("g() started");
    while (something)
        yield return null;
    Debug.Log("g() is done");
}

// Somewhere else you start f() like this:

StartCoroutine(f());

this will print:

"f() started"
"g() started"
"g() is done"
"f() is done"

If you still have trouble to understand how they work, take a look at this custom CoroutineScheduler. The author also have this great blog which explains a bit what happens behind the scenes