I'm really having a hard time understanding how Coroutines work in Unity. Here's the code I'm confused about:
StartCoroutine( ShowPlayerCoroutine() );
playerMesh.material = stealthMaterial;
yield return new WaitForSeconds( playerSpawnTime );
playerMesh.enabled = true;
First of all, the playerMesh.material does not get set when it is called where it is (after the co-routine. This only works when I put the assignment to .material after .enabled in ShowPlayerCoroutine().
This makes me wonder how coroutines work. I know that in coroutines, they will only return when a yield expression or end of function is encountered. However, since I'm not doing "yield StartCoroutine( ShowPlayerCoroutine() )", what does it do? I am told that StartCoroutine( ShowPlayerCoroutine() ) returns immediately, but does this mean that both Start() and ShowPlayerCoroutine() are running concurrently? I just can't visualize what the instruction pointer is doing in this case. Note that I am mainly a C++ programmer, and there is no similar construct in C++ for this behavior that I am aware of.
Answer by duck
Apr 19, 2010 at 08:55 PM
When you call StartCoroutine, you trigger what is almost like a process on a separate thread. It's not a separate thread however, so there's no concerns about thread-safety and locking access to variables. In addition, the code executing in your coroutine blocks execution of everything else completely (just as code in an Update() function would), except when it is told to pause and release control with a yield function.
So, when you start a coroutine, it starts running immediately, blocking the current execution of the function which started it, until it hits the first yield statement. The yield statement then causes execution to pause and the current position within the coroutine is stored. Execution then returns to the calling function. The value returned by yield specifies when the coroutine should start back up again - the smallest amount of time is after all the current frame's scripts have elapsed.
This means when you call
StartCoroutine( ShowPlayerCoroutine() );
your coroutine starts executing (blocking the Start() function), however on its first line, it reaches the yield function, and so returns - allowing the Start() function to resume and complete.
When it yielded - because of the value returned, it queued itself up to continue executing after "playerSpawnTime" seconds have elapsed. So the game continues playing for until that number of seconds have elapsed, at which point the coroutine will start back up again from the point at which it stopped.
Because Unity is not multithreaded (except for certain streaming operations), none of your code is ever executing at the same time. It is executed in a certain pre-determined order based on the queue of Update() events, FixedUpdate() events, coroutines which are now due to resume, and any other events which may be due to execute.
For more information, see: Event Execution Order on the Unity Wiki
Excellent answer, this really puts it into perspective for me. The guys at work tried to explain it but I think it just confused me more. Thanks a ton.
Even Unity's explanation is all over the place. But the above answer is the clearest one I've found so far. Thanks
Thanks a lot for this answer, it explain's a lot.
Answer by JC
Apr 19, 2010 at 08:54 PM
They are not executed concurrently. They go into a Stack/Queue and get executed in regular intervals.
The execution is halted in every yield and resumes from there when the yield that halted it ends.
WaitForSeconds in this case is like telling it to only execute the rest of the code when WaitForSeconds has ended its own execution.
Is that the actual code that's not working? That's probably because you're assingning the material while the Mesh is disabled. Not sure about that. :-/
Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.
The best place to ask and answer questions about development with Unity.
To help users navigate the site we have posted a site navigation guide.
If you are a new user, check out our FAQ for more information.
If you are a moderator, see our Moderator Guidelines page.
We are making improvements to UA, see the list of changes.
Answers and Comments
2 People are following this question.
Coroutines and waiting for a function to finish execution
Tracking state changes using yield
changing a coroutine's argument at the coroutine's runtime?
"Object reference required" error when using Start/StopCoroutine
suspend a function time to recover a data C#