Calling StartCoroutine multiple times seems to stack

Hello there. I’m new to C# and I noticed that if you call StartCoroutine multiple times the Coroutine seems to stack. I just want to know if this is a expected behavior.

I managed to “solve” this by using StopCoroutine(“MethodName”) BEFORE StartCoroutine(“MethodName”).

In the example bellow if I use OneCall the Amount result is around 535, if I use TwoCalls the result is around 1035 … and so on :

using UnityEngine;
using System.Collections;

public class CoroutineTest : MonoBehaviour {
	// true means that the StartCoroutine will be called once. 
	public bool OneCall = true;
	// true means that the StartCoroutine will be called twice.
	public bool TwoCalls = false;
	// Time in seconds that the test will be running.
	public float TestTime = 10f;
	// While looping times
	public int Amount = 0;
	
	
	void Start () {
                // First call
		StartCoroutine(Test ());
                // Second call (activate it in the Unity Editor)
		if(TwoCalls)StartCoroutine(Test ());
		StartCoroutine (StopTest());
	}
	

	IEnumerator StopTest()
	{
		yield return new WaitForSeconds(TestTime);
		OneCall = false;
	}

	
	IEnumerator Test()
	{
		Amount = 0;
		while(OneCall){
			++Amount;
			yield return null;
		}
	}
}

Yes, coroutines run independently, like separate threads. When you start a coroutine, an instance of it is created and starts running. If you start the same coroutine again, another instance is created and runs independently of the other, and so on.

This is a blessing in some special cases, but much more often may become a curse: if you start a coroutine each Update, for example (a very common error), a new instance will be created each frame, crowding the memory and eating the CPU time in a few minutes. To avoid this, a solution is to use a boolean variable that’s set when the coroutine starts and cleared upon finish, and check this variable before starting a the coroutine again - like this:

bool isRunning = false;

IEnumerator MyCoroutine(){
  isRunning = true;
  print("started");
  yield return new WaitForSeconds(3);
  print("3 seconds elapsed");
  yield return new WaitForSeconds(3);
  print("more 3 seconds");
  yield return new WaitForSeconds(2);
  print("ended");
  isRunning = false;
}

void Update(){
  if (!isRunning) StartCoroutine(MyCoroutine());
}

This code will call MyCoroutine repeatedly, but only one instance at a time due to the flag isRunning - if you don’t check it, a new MyCoroutine will be created each frame. At 50 frames per second, for instance, you may have about 400 MyCoroutine instances running at the same time (each one lives for 8 seconds).