在循环中使用Coroutine,如何等待协程的WaitForSeconds结束后继续执行
协程与循环配合时序问题解决方案
原因说明
你现在遇到的打印语句立刻执行的问题,本质是StartCoroutine()本身是非阻塞方法:调用它只是把协程加入Unity的协程调度队列,不会卡住当前方法的执行流程,所以协程里的WaitForSeconds只会阻塞协程内部的后续代码,不会阻塞调用StartCoroutine()的外层方法,自然打印语句就会跟着myAudio.Play()立刻执行。
推荐解决方案
方案1:将整个循环逻辑移入协程(最常用)
直接把循环、音频播放、等待、后续逻辑都放在同一个协程里,用yield return控制执行顺序即可:
/// <summary> /// 主循环协程 /// </summary> /// <param name="loopTimes">循环次数</param> /// <param name="waitSeconds">每次播放音频后等待的时长</param> IEnumerator AudioPlayLoop(int loopTimes, float waitSeconds) { for (int i = 0; i < loopTimes; i++) { myAudio.Play(); // 等待指定时长,之后才会执行后续代码 yield return new WaitForSeconds(waitSeconds); Debug.Log("Now I am executed"); // 你需要的额外终止条件可以写在这里,满足就直接跳出循环 // if (终止条件满足) break; } }
需要启动逻辑的时候调用一次即可:
StartCoroutine(AudioPlayLoop(你需要的循环次数, 等待的秒数));
方案2:外层协程等待子协程执行完毕
如果你的等待逻辑已经封装为独立的协程,不需要改动,可以在外层协程里通过yield return StartCoroutine(子协程())的写法,等待子协程完全执行完再进入下一轮循环:
// 你已有的独立等待协程 IEnumerator WaitForTime(float waitTime) { yield return new WaitForSeconds(waitTime); // 其他协程内部逻辑 } // 主控制协程 IEnumerator MainControlCoroutine(int loopTimes) { for (int i = 0; i < loopTimes; i++) { myAudio.Play(); // 等待子协程完全执行完毕,才会继续往下走 yield return StartCoroutine(WaitForTime(2f)); Debug.Log("Now I am executed"); } }
额外提示:等待过程中持续检查条件
如果你的需求是等待时长结束前要持续检查某个终止条件,满足就提前结束等待,可以替换WaitForSeconds为逐帧判断逻辑:
IEnumerator AudioPlayLoop(int loopTimes, float maxWaitSeconds) { for (int i = 0; i < loopTimes; i++) { myAudio.Play(); float passedTime = 0; bool conditionMeet = false; while (passedTime < maxWaitSeconds) { passedTime += Time.deltaTime; // 每一帧检查是否满足终止条件 if (你的终止条件) { conditionMeet = true; break; } // 等待一帧后再判断 yield return null; } Debug.Log("Now I am executed,等待终止原因:" + (conditionMeet ? "满足终止条件" : "等待时长结束")); } }
内容的提问来源于stack exchange,提问作者sarahrht
相关产品推荐
相关产品推荐

