Execution manner of co routine

Hi, these are my code

using UnityEngine;
using System.Collections;

public class sample : MonoBehaviour {

	// Use this for initialization
	void Start () {	
	
	}
	
	// Update is called once per frame
	void Update () {

		if (Input.GetKeyDown("space"))
		{
		    print ("called before coroutine");
			StartCoroutine("testCOR");
		    print ("called after coroutine");
		}
		print ("this is end of frame.");
	
	}
	IEnumerator testCOR()
	{
		for(int i=0;i<3;i++)
		{
			print ("Now number is: "+i);
			print ("Just before coroutine");
			yield return null;
		}
	}
}

When I press spaceBar just one time, the result pattern I am expecting is:

....................
....................
this is end of frame.
this is end of frame.
this is end of frame.
called before coroutine
Now number is: 0
Just before coroutine
called after coroutine
this is end of frame.

called before coroutine
Now number is: 1
Just before coroutine
called after coroutine
this is end of frame.


called before coroutine
Now number is: 2
Just before coroutine
called after coroutine
this is end of frame.

called before coroutine
called after coroutine
this is end of frame.
this is end of frame.
this is end of frame.

In stead I am getting the following:

    ....................
    ....................
    this is end of frame.
    this is end of frame.
    this is end of frame.
    called before coroutine
    Now number is: 0
    Just before coroutine
    called after coroutine
    this is end of frame.
    this is end of frame. //why twice. Is unity taking two frames?
    
    Now number is: 1
    Just before coroutine
    this is end of frame. //where is "called after coroutine"? 
    
    Now number is: 2
    Just before coroutine
    this is end of frame.
    this is end of frame.
    ....................
    ....................

When I press spaceBar again, I got these:

....................
....................
this is end of frame.
this is end of frame.
called before coroutine
Now number is: 0
Just before coroutine
called after coroutine
this is end of frame.
this is end of frame.

Now number is: 1
Just before coroutine
this is end of frame.

Now number is: 2
Just before coroutine
this is end of frame.
this is end of frame.
....................
....................

The dots means I am getting “this is end of frame.” line continuously forever.

So, each time I press spaceBar, I get similar pattern. Probably coroutine does not work like the way I thought. But how does they execute? I need to know this. It is now such a mystery to me now. I thought like these:

when you encounter yield statement, control flow jumps from coroutine to next line of “startCoroutine()” and then finishes rest of the jobs in update() method. After finishing, flow returns(of course after lateUpdate and other stuffs) to again Update method. This time flow goes to co-routine again. But “with having previous state”. Loops goes on and on until the “forLoop” does not let it go further. Then flow again returns to update method and completes the rest jobs to render that frame. This happens whenever something triggers the coroutine.

If we use coroutine’s yield like “waitforFixedUpdate” manner,then execution resume on next physics change instead of next frame. If we use “waitForEndOfFrame”, then execution resume after LateUpdate and rendering(GUI drawing?) on next frame in stead of next frame on “update” method. That means coroutine will not execute while we are on update method if we use “waitForEndOfFrame”. Rather it will execute when we finish drawing our frame.

So those were my thoughts on coroutine. Clearly I was wrong. But what is right regarding Coroutine. Please shed some lights on it. It is driving me crazy!

So I will be answering my own question. Ok. the concept of program counter(PC) is very important. When you run any computer program, binary executes line by line. “Something” reads a line and executes it, then moves it to next line. This “something” is called PC. It is actually a pointer that holds the address of “next instruction to execute”. Lets look at the following simple C++ program.

    Line 1 #include<iostream>
    Line 2 using namespace std;       
    Line 3 void anotherMessage()
    Line 4 {
    Line 5 cout<<"yet another message";
    Line 6 }       
    Line 7 int main()
    Line 8 {
    Line 9 cout<<"Hi there!";
    Line 10 showMeMessage();
    Line 11 return 0;   
    Line 12 }        
    Line 13 void showMeMessage()
    Line 14 {
    Line 15   cout<<"this is the message";
    Line 16 }

Ok.Lets think as a machine. First I will look on a file called “iostream.h” sothat I will know how to print something. Then with “using namespace std;” I realized all the names are standard. Meaning “cout” “endl” etc means something which is standard. If we do not do it then I might say cout is for “a command to get out of comod”!. This is pre-processing. After preprocessing, actual execution happen first at main method. I shall not look at “void anotherMessage()” or “void showMeMessage()” first. First I will look at main method. Main is our entry point. So PC will be at first on “main()” method. Then I first print “hi there”. Then I encounter a showMeMessage() method. Then I go straight its definition. After that I print “this is the message”. Then I return 0 and exit. So the pattern of PC by line number is:
1>2>7>8>9>10>13>14>15>16>11>12

Now I will explain how coroutine execute as same manner. head up to my first code. Carefully get the line numbers.
This frame we are at line number 12, update method. Then 13>14. Are we pressing spacebar now at 14? Lets say we not. So jump into 20. On the next frame, program detect we pressed spacebar. So what will happen?

12>13>14>15>16>17 then it will find a coroutine and will execute it. So after 17,it will be on 23.
23>24>25>26>27>28>29. On 29, we see null(if we do not,lets say we find another coroutine after return. Then PC will go there. You can nest endless coroutine I guess), so we go to 30 and then:

30>18>19. Mark this position. After 19, we are out from the code block of if statement.
19>20>21>22

Thus on this frame(the frame program detects a “spacebar press”), we have this pattern for the sample code:
12>13>14>15>16>17>23>24>25>26>27>28>29>30>18>19>20>21>22

Now on the next frame, program will not detect a “spacebar press” if we do not hit spacebar again. For simplicity, lets assume, we haven’t hit any key. So what will happen on next frame. Remember we haven’t completed for loop as we returned an yield when we have i=0. So when will we resume. How will PC move this time?

12>13>14. it does not detect any spacebar hit, so code block of if statement “will not execute”. Thus after 14,
20>21>22.Wait a min,we haven’t resumed our coroutine. Yes gentleman, now we will resume. So after 22, we will not move to next frame. Rather,

23>24>25>26>27>28>29>30. After this we will move on next frame. On next frame we will not register any spaceBar. So, similar pattern will goes on and on until we are done with coroutine(i>=3).

One question remain, if we constantly pressing spaceBar.Meaning, on each frame we detect spaceBar hit, what will happen?[edit: at first, it will complete first invocation. When first coroutine instance is complete, it will go to second one. And thus it goes on and on] After first coroutine invocation, next invocation will wait for finishing of current one? or things will go mess up? Probably another guru will clear up. And I can do some experiments!

So the summery of this long post is: After first yield, it will resume when next frame will complete everything, not in the middle!

EDIT 1:

I have found some interesting ideas. It is about nested coroutines.

what will happen when you do like:

yield return StartCoroutine("anotherCOR");

when anotherCOR() looks like similar to:

IEnumerator anotherCOR()
{
 for(int i=0;i<3;i++)
 {
  print ("Now number is: "+i);
  print ("Just before coroutine");
  yield return null;
 }
}

Well on each invocation of testCOR(), at first anotherCOR() has to be completed. This means: for i=0 of testCOR(), at first i of anotherCOR() has to be 0-1 and then 2. Only then next invocation of testCOR will happen. I guess we can nest another like:

IEnumerator anotherCOR()
 {
   for(int i=0;i<3;i++)
   {
    print ("Now number is: "+i);
    print ("Just before coroutine");
    yield return StartCoroutine("yetAnotherCOR");
   }
 }

Much like nested if-else. I am thinking its practical use. What it can be?!

StartCoroutine will create an instance of the coroutine that will run it’s course independantly of the Update function. If you press space several times, you’ll have several instances. If you want an in-depth explaination, check this out : http://www.altdevblogaday.com/2011/07/07/unity3d-coroutines-in-detail/

For your problem, insert the prints “before” and “after” inside the for loop of the coroutine.