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

如何在敌人攻击的时间窗口内检测防御按键并执行对应动作?

问题分析与修复方案

核心问题

  • 重复启动协程:Update每帧检测动画播放状态,只要攻击动画在运行就会启动新的DefendTiming协程,导致同一攻击触发多次判定逻辑,出现异常。
  • 状态管理混乱:defendButtonPressed和receivedDamage没有在攻击结束后重置,后续攻击无法正确判断玩家操作。
  • 判定时机偏差:等待整个动画时长再判定,不符合“攻击时机”的设计逻辑,应该在动画的特定命中帧触发判定。

修复代码示例

1. 添加状态标记,避免重复执行

先在类中添加布尔变量,标记当前是否正在处理攻击判定:

private bool isProcessingAttack = false;

2. 修改Update中的检测逻辑

只有当攻击动画播放且未在处理判定时,才启动协程:

void Update()
{
    bool isAttackPlaying = enemy.CheckIfAnimationIsPlaying("Enemy_mainAttack") || 
                          enemy.CheckIfAnimationIsPlaying("Enemy_mainAttack2") || 
                          enemy.CheckIfAnimationIsPlaying("Enemy_firstAttack");

    if (isAttackPlaying && !isProcessingAttack)
    {
        isProcessingAttack = true;
        StartCoroutine(DefendTiming());
    }

    // 防御按键检测(替换为你的实际按键)
    if (Input.GetKeyDown(KeyCode.LeftShift))
    {
        defendButtonPressed = true;
    }
}

3. 优化判定逻辑(推荐用动画事件)

在攻击动画的命中帧添加Animator事件,直接调用判定方法,精准控制时机:

// 敌人动画事件绑定的方法(挂在敌人对象上)
public void TriggerAttackCheck()
{
    if (!defendButtonPressed && !receivedDamage)
    {
        ReceiveDamage(enemy.attack);
        receivedDamage = true;
    }
    else
    {
        ReduceEndurance(false, 3);
    }
}

// 协程仅负责攻击结束后的状态重置
private IEnumerator DefendTiming()
{
    AnimatorStateInfo stateInfo = enemy.animator.GetCurrentAnimatorStateInfo(0);
    yield return new WaitForSeconds(stateInfo.length);

    // 重置所有状态,确保下一次攻击正常判定
    isProcessingAttack = false;
    defendButtonPressed = false;
    receivedDamage = false;
}

4. 备选方案:无动画事件时的优化

如果暂时不用动画事件,可调整协程的等待时间,瞄准攻击判定窗口:

private IEnumerator DefendTiming()
{
    AnimatorStateInfo stateInfo = enemy.animator.GetCurrentAnimatorStateInfo(0);
    // 假设判定时机在动画进行到70%的位置(可根据实际调整)
    float judgeWindowTime = stateInfo.length * 0.7f;
    yield return new WaitForSeconds(judgeWindowTime);

    // 执行判定逻辑
    if (!defendButtonPressed && !receivedDamage)
    {
        ReceiveDamage(enemy.attack);
        receivedDamage = true;
    }
    else
    {
        ReduceEndurance(false, 3);
    }

    // 等待动画结束后重置状态
    yield return new WaitForSeconds(stateInfo.length - judgeWindowTime);
    isProcessingAttack = false;
    defendButtonPressed = false;
    receivedDamage = false;
}

额外优化建议

把攻击动画名称整理成常量数组,避免硬编码:

private readonly string[] _attackAnimations = { "Enemy_mainAttack", "Enemy_mainAttack2", "Enemy_firstAttack" };

后续检测时用遍历简化逻辑:

bool isAttackPlaying = _attackAnimations.Any(anim => enemy.CheckIfAnimationIsPlaying(anim));

内容的提问来源于stack exchange,提问作者pauSei

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:05:25