在 Unity 中,不同的"yield return X"协程是否总是按顺序运行?



【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);
}
}

【输出】

A1
A2
A3
A1
A2
A3
A1
A2
A3
A1
A2
A3

【我的问题】

A1(),A2(),A3()总是按顺序运行。

是确定的还是不确定的?
yield return null" yield return WaitForSeconds"和其他"收益回报x"?

为什么我有这个问题?
在Unity的事件函数的执行顺序中,不同类型的"yield return X"发生在不同的时间。
然后我想知道,如果几个相同类型的"yield返回X"(在同一个MonoBehaviour)总是按顺序发生。

<标题>

Update1 h1>在评论中,@joreldraw说

将A1更改为20秒,A2更改为10秒,然后再试一次:)

下面是代码和输出。

【代码】

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);
}
}

【输出】

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

1.2

我想知道的是,当它们在同一帧时,它们是否保持顺序。
所以我把时间改为0.01秒和0.02秒。

【输出】

A1,框架:3,时间:0.3533334
A2,框架:3,时间:0.3533334

A2,frame:10,time:0.4100522
A1,frame:11,time:0.4132612
A1,frame:15,time:0.4247341

A1,框架:38岁的时间:0.4942196
A2,框架:38岁,时间:0.4942196

A2,框架:52,时间:0.5754243
A1,框架:52岁,时间:0.5754243
A1,框架:54岁,时间:0.5914614

1.3

很难找出如果协同程序维持秩序。所以我修改了代码,只在协程运行在同一帧时才打印。

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);
}
}

【输出】


第一个1,然后2,帧:3
第一个1,然后2,帧:4
第一个2,然后1,帧:9
第一个2,然后1,帧:16
第一个2,然后1,帧:22
第一个2,然后1,帧:76
第一个1,然后2,帧:135
第一个1,然后2,帧:179
第一个2,然后1,帧:186
第一个1,然后2,帧:222

在你描述的情况下,是的!顺序总是一样的,因为你一个接一个地开始,它们都要等3秒,所以第一个总是先开始。对于yield return null也是一样的因为它会在下一帧执行。当您从不同的Update()/start()方法启动这些例程时,会变得很棘手,因为这些例程的执行顺序没有得到保证。如果你需要它们以特定的顺序执行,尝试不同的等待间隔或使用这里描述的其他unity函数:https://docs.unity3d.com/Manual/ExecutionOrder.html?_ga=2.194867501.1256475209.1612055407-571780476.1550264998#Coroutines

协程的开始遵循代码的顺序:

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

协程的结果取决于您为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);
}

最新更新