如何正确实现三段剑击连击动画?现有触发异常问题求助
三段剑击连击动画实现问题
遇到的问题
- 首次输入三次攻击指令时,第三段动画需第四次点击才会播放;
- 连续快速点击时,第一段动画要在三次快速点击后才会播放,且需等第三段动画结束后才会执行。
期望效果
每点击一次触发对应段动画(第1次点击触发Attack、第2次触发Attack2、第3次触发Attack3),连击完成后再次点击可重新开始三段连击。
现有代码
public class swordscript : MonoBehaviour { public GameObject Sword; private Animator anim; private int comboStep = 0; // 当前连击阶段 private float lastComboTime = 0f; // 上次攻击的启动时间 private float comboTimeout = 1.0f; // 连击完成的时间窗口 private float ResetAtkCooldown = 0.5f; void Start() { // 获取Sword对象上的Animator组件 anim = Sword.GetComponent<Animator>(); } void Update() { // 检测玩家鼠标左键点击 if (Input.GetMouseButtonDown(0)) { // 检查是否处于连击时间窗口内 if (Time.time - lastComboTime <= comboTimeout) { // 递增连击阶段 comboStep++; // 根据当前阶段执行对应动作 switch (comboStep) { case 1: anim.SetTrigger("Attack"); StartCoroutine(ResetToIdle()); break; case 2: anim.SetTrigger("Attack2"); StartCoroutine(ResetToIdle()); break; case 3: anim.SetTrigger("Attack3"); StartCoroutine(ResetToIdle()); break; default: // 连击阶段超过3时重置为1 if (comboStep > 3) { comboStep = 1; } break; } } else { // 超时,启动新连击 comboStep = 1; } // 记录上次攻击时间 lastComboTime = Time.time; } } IEnumerator ResetToIdle() { yield return new WaitForSeconds(ResetAtkCooldown); comboStep = 0; } }
问题分析与优化方案
问题根源
- 重复协程干扰状态:每次触发动画都启动
ResetToIdle协程,多个协程会在不同时间点将comboStep重置为0,导致点击时的阶段数值不符合预期(比如第三次点击时,前序协程已把comboStep重置为0,导致触发的是第一段而非第三段)。 - 连击阶段逻辑混乱:快速点击时,
comboStep被多次递增,但协程的延迟重置会打乱阶段顺序,造成动画触发滞后。
优化后的代码
public class swordscript : MonoBehaviour { public GameObject Sword; private Animator anim; private int comboStep = 0; // 当前连击阶段 private float lastComboTime = 0f; // 上次攻击的时间 private float comboTimeout = 1.0f; // 连击超时窗口 private Coroutine resetComboCoroutine; // 控制连击重置的协程 void Start() { anim = Sword.GetComponent<Animator>(); } void Update() { if (Input.GetMouseButtonDown(0)) { // 判断是否在连击超时窗口内 if (Time.time - lastComboTime <= comboTimeout) { // 未完成连击则递增阶段,完成则重置为第一段 comboStep = comboStep < 3 ? comboStep + 1 : 1; } else { // 超时后启动新连击 comboStep = 1; } // 触发对应阶段的动画 TriggerAttackAnimation(comboStep); // 更新上次攻击时间 lastComboTime = Time.time; // 停止之前的重置协程,避免重复修改状态 if (resetComboCoroutine != null) { StopCoroutine(resetComboCoroutine); } // 启动新的超时重置协程 resetComboCoroutine = StartCoroutine(ResetComboAfterTimeout()); } } /// <summary> /// 根据连击阶段触发对应动画 /// </summary> void TriggerAttackAnimation(int step) { switch (step) { case 1: anim.SetTrigger("Attack"); break; case 2: anim.SetTrigger("Attack2"); break; case 3: anim.SetTrigger("Attack3"); break; } } /// <summary> /// 连击超时后重置阶段 /// </summary> IEnumerator ResetComboAfterTimeout() { yield return new WaitForSeconds(comboTimeout); comboStep = 0; resetComboCoroutine = null; } }
优化核心点
- 单一协程控制重置:每次点击时停止之前的重置协程,仅保留最新的一个,避免多个协程同时修改
comboStep。 - 清晰的阶段流转逻辑:连击完成(阶段3)后,再次点击直接回到第一段;超时后才重置为初始状态,确保连击流程连贯。
- 分离动画触发逻辑:将动画触发封装为独立方法,代码结构更清晰,便于维护。
修改后可实现:第一次点击触发Attack、第二次触发Attack2、第三次触发Attack3,第四次点击(超时内)回到Attack;超时后点击重新启动三段连击,完全符合预期效果。
内容的提问来源于stack exchange,提问作者zed 787
相关产品推荐
相关产品推荐

