@jwatte:
Forget about threading. I know it’s counter intuitive but coroutines are not about letting something run in another thread. This is only the way they are implemented in let’s say Lua. And the Coroutines in Lua cannot be used like the ones in Unity. They work differently.
Unity Coroutines are all running in the same thread, the main thread where anything else runs.
The coroutine does not stall the thread. It returns on every yield return something. So if you see a yield return null in the code, this is the place the function returns. It resumes at the following line in the next frame.
So it works like a Tick() function, but it maintains state automatically. A sample:
public delegate void voidFunc(); // called when action is completed, given by clients
public void MyDelay(float secs, voidFunc callBack)
{
curCoroutine = CoDelay(secs, callBack);
StartCoroutine(curCoroutine);
}
IEnumerator CoDelay(float delay, voidFunc callBack)
{
while (delay > 0f)
{
delay -= Time.deltaTime;
yield return null;
}
if (callBack != null) callBack();
}
// anywhere in your application:
public void PleaseCallMeBack()
{
// do something
}
MyDelay(3.1415f, PleaseCallMeBack);
This does exactly what it looks like. Call MyDelay() anywhere and a few seconds later you will receive a callback. May be typos in there, just hacked it in a minute.
The point is, the state of ‘delay’ is automatically kept. You don’t have to care about it. All coroutines are updated at some point in the update loop, so there is no multithreading. Your callback (or anything else) must **not **be thread save.
It’s an update without a Tick() and without keeping state by yourself. Don’t ask me how they did it, I don’t know.
I know this looks like magic for a C++ programmer (it appeared this way to me though), but it works perfectly.
EDIT: the reason for checking ‘if (callBack != null)’ is only convenience. It will not become invalid at some time. Copy&Paste, you know.