How do I do something after multiple coroutines finish?

I am trying to call a function after all the coroutines called in a function have finished

void f()
{
  Debug.Log("First");

  Queue<Vector2> vectors = new Queue<Vector2>();
  vectors.enqueue(Vector2.up);
  vectors.enqueue(Vector2.right);
  vectors.enqueue(-Vector2.up);
  vectors.enqueue(-Vector2.right);

  foreach(Vector2 v in vectors){
    StartCoroutine(g(v));
  }
}

IEnumerator g(Vector2 v)
{
  Debug.Log(v);

  // This is just an example. Not what I am really doing
  yield return new WaitForSeconds(2*v.x*v.x+3*v.y*v.y);

  h()
}

void h()
{
  Debug.Log("Last");
}

The console will result in this

First
(0.0,1.0)
(1.0,0.0)
(0.0,-1.0)
(-1.0,0.0)
Last
Last
Last
Last

How can I set up my code to not call the last function multiple times?


I have also tried this:

void f()
{
  StartCoroutine(g(vectors));
}

IEnumerator g(Queue<Vector2> vectors)
{
  foreach(Vector2 v in vectors){
    yield return new WaitForSeconds(t);
  }
  h()
}

This ends up doing each one consecutively instead of simultaneously.

You need to share data between your coroutines.

Depending on your usage either add a new member to your class, eg:

int runningCoroutines;

and set it to vectors.Count before starting the coroutines. Decrement it in g() and only call h() when runningCoroutines is zero.

or, when f() is called multiple times, create a shared container having the runningCoroutines member. Eg

class SharedData
{ 
    public int runningCoroutines;
}

which you instantiate once and pass to each coroutine.

Note: Coroutines are never executed in parallel, so sharing data between them is very easy. There are eg no run conditions.