Home > front end >  In Unity, does different "yield return X" Coroutine always run in order?
In Unity, does different "yield return X" Coroutine always run in order?

Time:10-13

【code】

private void Start()
{
    StartCoroutine(A1());
    StartCoroutine(A2());
    StartCoroutine(A3());
}

IEnumerator A1()
{
    while (true)
    {
        print("A1");
        yield return new WaitForSeconds(3);
    }
}
IEnumerator A2()
{
    while (true)
    {
        print("A2");
        yield return new WaitForSeconds(3);
    }
}
IEnumerator A3()
{
    while (true)
    {
        print("A3");
        yield return new WaitForSeconds(3);
    }
}

【output】

A1
A2
A3
A1
A2
A3
A1
A2
A3
A1
A2
A3
...

【My Quesion】

A1(),A2(),A3() always run in order.

Is it for sure or not?
Is it the same for "yield return null", "yield return WaitForSeconds" and other "yield return X"?

Why I have this question?
In Unity's Order of execution for event functions, different kinds of "yield return X" happens at different time.
Then I want to know, if several same kind of "yield return X"(in the same MonoBehaviour) always happens in order.

Update1

1.1

In the comment, @joreldraw says

Change your A1 to 20 seconds, A2 to 10, and try again :)

Here is code and output.

【code】

private void Start()
{
    StartCoroutine(A1());
    StartCoroutine(A2());
}

IEnumerator A1()
{
    while (true)
    {

        print($"A1,frame:{Time.frameCount},time:{Time.time}");
        yield return new WaitForSeconds(10f);
    }   
}
IEnumerator A2()
{
    while (true)
    {

        print($"A2,frame:{Time.frameCount},time:{Time.time}");
        yield return new WaitForSeconds(20f);
    }
}

【output】

A1,frame:3187,time:10.00139
A2,frame:6495,time:20.0001
A1,frame:6496,time:20.00392
A1,frame:9686,time:30.00965
A2,frame:13093,time:40.0004
A1,frame:13095,time:40.01266
A1,frame:16445,time:50.01303
A2,frame:19695,time:60.00157
A1,frame:19699,time:60.01489

1.2

What I want to know is, if they keep in order when they are at same frame.
So I change time to 0.01s and 0.02s .

【output】

A1,frame:3,time:0.3533334
A2,frame:3,time:0.3533334
...
A2,frame:10,time:0.4100522
A1,frame:11,time:0.4132612
A1,frame:15,time:0.4247341
...
A1,frame:38,time:0.4942196
A2,frame:38,time:0.4942196
...
A2,frame:52,time:0.5754243
A1,frame:52,time:0.5754243
A1,frame:54,time:0.5914614
...

1.3

It is hard to figure out if the coroutines keep in order. So I modified code, only do printing when the coroutines run at the same frame.

HashSet<int> a1Set = new HashSet<int>();
HashSet<int> a2Set = new HashSet<int>();
private void Start()
{
    StartCoroutine(A1());
    StartCoroutine(A2());
}

IEnumerator A1()
{
    while (true)
    {
        a1Set.Add(Time.frameCount);
        if (a2Set.Contains(Time.frameCount))
        {
            print($"First 2, Then 1, frame:{Time.frameCount}");
        }
        yield return new WaitForSeconds(0.01f);
    }   
}
IEnumerator A2()
{
    while (true)
    {
        a2Set.Add(Time.frameCount);
        if (a1Set.Contains(Time.frameCount))
        {
            print($"First 1, Then 2, frame:{Time.frameCount}");
        }
        yield return new WaitForSeconds(0.02f);
    }
}

【output】

First 1, Then 2, frame:3
First 1, Then 2, frame:4
First 2, Then 1, frame:9
First 2, Then 1, frame:16
First 2, Then 1, frame:22
First 2, Then 1, frame:28
First 1, Then 2, frame:76
First 1, Then 2, frame:135
First 1, Then 2, frame:179
First 2, Then 1, frame:186
First 1, Then 2, frame:222

CodePudding user response:

In your described case yes! The order is always the same because you start them one after another and they all wait 3 seconds so the first ones always has the head start. It's the same for yield return null because then it's executed in the next frame. It gets tricky when you start the couroutines from different Update()/Start() methods because the exectuion order of those is not guaranteed. If you need them to execute in a specific order try different wait intervals or use other unity functions described here: https://docs.unity3d.com/Manual/ExecutionOrder.html?_ga=2.194867501.1256475209.1612055407-571780476.1550264998#Coroutines

CodePudding user response:

The start of the coroutine follow the order of your code:

private void Start()
{
    StartCoroutine(A1()); //Firt
    StartCoroutine(A2()); //Second
}

The result of the coroutine depend of the time of execution you add for wait:

IEnumerator A1()
{
    Debug.Log("Started Coroutine A1 at : "   Time.time);
     yield return new WaitForSeconds(0.01f);

     //Here your code for the result after waitforsecond
     Debug.Log("Finished Coroutine A1 at : "   Time.time);   
}
IEnumerator A2()
{
     Debug.Log("Started Coroutine at A2 : "   Time.time);
     yield return new WaitForSeconds(0.02f);

     //Here your code for the result after waitforsecond
     Debug.Log("Finished Coroutine A2 at : "   Time.time);
}
  • Related