如何避免代码每帧执行yield?优化递归协程遍历地形的性能问题
解决递归协程频繁yield导致的性能问题
首先,你的核心问题有两个:
- 全局的
timer变量在递归调用的多个crC协程实例中共享,导致计数逻辑混乱,根本无法准确控制每100步才yield一次 - 每次递归调用
yield return StartCoroutine(crC())会让每个递归分支都可能触发yield,最终导致每帧都在暂停,拖慢了整体处理速度
解决方案思路
- 将计数器改为局部参数传递:避免多个递归协程互相干扰计数逻辑
- 统一控制yield触发时机:在递归过程中累计处理的步数,只有当累计到100步时才主动yield一次,而非每个递归分支都触发暂停
修改后的伪代码示例
void Awake(){ StartCoroutine(crA()); } public IEnumerator crA(){ // 前置处理逻辑 yield return StartCoroutine(crB()); // 只有crB完全执行完才会走到这里的逻辑 } public IEnumerator crB(){ // 初始步数从0开始传入 yield return StartCoroutine(crC(0)); } // 把步数计数器作为参数传入,避免全局变量的多协程干扰 public IEnumerator crC(int stepCount){ // 地形遍历、创建区域的核心逻辑 if(x){ yield break; } stepCount++; // 每累计100步才触发一次yield if (stepCount >= 100){ stepCount = 0; yield return null; } // 递归调用时传递当前的步数计数器,保证计数连续 yield return StartCoroutine(crC(stepCount)); yield return StartCoroutine(crC(stepCount)); yield return StartCoroutine(crC(stepCount)); yield return StartCoroutine(crC(stepCount)); yield return StartCoroutine(crC(stepCount)); }
关键修改说明
- 局部计数器:将全局
timer改为crC的参数stepCount,每个递归分支都会携带自己的计数,不会出现多个协程互相覆盖计数的问题 - 统一yield触发:只有当当前协程的累计步数达到100时,才会暂停一帧,而非每个递归调用都触发暂停。这样每100步才会让程序让出帧时间,大幅提升处理效率
- 避免全局变量污染:全局变量在多协程场景下很容易出现逻辑漏洞,改用参数传递的方式更安全可控
如果后续还是担心递归深度可能引发栈溢出,可以考虑把递归逻辑改成迭代方式(比如用栈结构模拟递归过程),不过如果当前递归深度在可控范围内,上面的修改已经能解决你的核心问题。
内容的提问来源于stack exchange,提问作者flask
相关产品推荐
相关产品推荐

