x


Coroutine confusion

I'm really having a hard time understanding how Coroutines work in Unity. Here's the code I'm confused about:

void Start() { StartCoroutine( ShowPlayerCoroutine() ); playerMesh.material = stealthMaterial; }

IEnumerator ShowPlayerCoroutine() { 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.

more ▼

asked Apr 19, 2010 at 08:01 PM

Robert 1 gravatar image

Robert 1
379 47 38 48

(comments are locked)
10|3000 characters needed characters left

2 answers: sort voted first

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

more ▼

answered Apr 19, 2010 at 08:55 PM

duck gravatar image

duck ♦♦
47.8k 131 233 472

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.

Apr 21, 2010 at 01:34 PM Robert 1

Even Unity's explanation is all over the place. But the above answer is the clearest one I've found so far. Thanks

Oct 29, 2012 at 10:43 AM netlander

Thanks a lot for this answer, it explain's a lot.

Mar 01, 2013 at 05:28 PM Steven 1
(comments are locked)
10|3000 characters needed characters left

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. :-/

more ▼

answered Apr 19, 2010 at 08:54 PM

JC gravatar image

JC
105 13 9 20

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x634

asked: Apr 19, 2010 at 08:01 PM

Seen: 8928 times

Last Updated: Mar 01, 2013 at 05:28 PM