You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免代码每帧执行yield?优化递归协程遍历地形的性能问题

解决递归协程频繁yield导致的性能问题

首先,你的核心问题有两个:

  • 全局的timer变量在递归调用的多个crC协程实例中共享,导致计数逻辑混乱,根本无法准确控制每100步才yield一次
  • 每次递归调用yield return StartCoroutine(crC())会让每个递归分支都可能触发yield,最终导致每帧都在暂停,拖慢了整体处理速度

解决方案思路

  1. 将计数器改为局部参数传递:避免多个递归协程互相干扰计数逻辑
  2. 统一控制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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 22:03:11