Unity耐力系统开发问题:多次调用时仅保留最后一次协程
解决耐力系统多次调用时的协程冲突问题
我明白你的痛点——每次攻击触发耐力消耗后,之前的恢复协程还在后台跑,导致多次恢复叠加,完全不符合“只保留最后一次调用效果”的需求。咱们来一步步修复这个问题:
核心问题分析
你当前的代码每次触发时都会启动新的TimerStamina协程,之前启动的协程并没有被终止,它们依然会在5秒后执行恢复逻辑。这就导致了多次恢复操作同时进行,逻辑完全乱套了。
解决方案思路
要实现“取消之前调用,保留最后一次”的效果,关键是每次触发新的耐力消耗时,先终止所有正在运行的相关协程,再启动新的协程。我们需要:
- 保存协程的引用,这样才能随时终止它们
- 在启动新协程前,检查并终止旧的协程
- 修正恢复逻辑,确保只恢复本次消耗的耐力值(而不是盲目循环到maxStamina)
修改后的完整代码
// 保存协程引用,方便后续取消 private Coroutine _currentTimerCoroutine; private Coroutine _currentRecoveryCoroutine; // 记录本次消耗的耐力值,用于精准恢复 private int _lastStaminaCost; public void ConsumeStamina(int cost) { Debug.Log("Etapa 0: 触发耐力消耗"); // 先取消所有正在运行的相关协程 if (_currentTimerCoroutine != null) { StopCoroutine(_currentTimerCoroutine); _currentTimerCoroutine = null; } if (_currentRecoveryCoroutine != null) { StopCoroutine(_currentRecoveryCoroutine); _currentRecoveryCoroutine = null; } // 执行耐力消耗逻辑 if (currentStamina >= cost) { currentStamina -= cost; _lastStaminaCost = cost; // 启动新的延迟恢复协程 _currentTimerCoroutine = StartCoroutine(TimerStamina()); Debug.Log("Etapa 1: 耐力已消耗,启动恢复倒计时"); } else { Debug.Log("耐力不足,无法攻击"); } } IEnumerator TimerStamina() { yield return new WaitForSeconds(5); // 启动恢复协程并保存引用 _currentRecoveryCoroutine = StartCoroutine(RestartStamina()); Debug.Log("Etapa 2: 倒计时结束,开始恢复耐力"); } IEnumerator RestartStamina() { int recoveredAmount = 0; // 只恢复本次消耗的耐力值,避免过度恢复 while (recoveredAmount < _lastStaminaCost && currentStamina < maxStamina) { Debug.Log("Etapa 3: 恢复1点耐力"); currentStamina++; recoveredAmount++; yield return regenTick; } Debug.Log("Etapa 5: 耐力恢复完成"); // 恢复完成后清空协程引用 _currentRecoveryCoroutine = null; }
关键修改点说明
- 协程引用变量:
_currentTimerCoroutine和_currentRecoveryCoroutine用来跟踪当前运行的协程,这样我们能随时终止它们。 - 取消旧协程:每次触发消耗时,先停止之前的倒计时和恢复协程,确保只有最新的一次生效。
- 精准恢复:用
_lastStaminaCost记录本次消耗的数值,恢复时只补回这些数值,避免原来代码中可能出现的过度恢复问题。 - 边界判断:在恢复循环中加入
currentStamina < maxStamina的判断,防止耐力超过上限。
这样修改后,不管你多少次触发耐力消耗,之前的协程都会被立即终止,只有最后一次的5秒倒计时和恢复逻辑会执行,完美符合你的需求!
内容的提问来源于stack exchange,提问作者andrei
相关产品推荐
相关产品推荐

