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

Unity C#:按C键随机播放单次攻击动画的代码问题排查

问题原因与修复方案

你的代码之所以一次按键触发多次动画,核心问题是用了Input.GetKey(KeyCode.C)——这个API会在按住C键的每一帧都执行代码块。哪怕你只是快速按一下C键,游戏帧率通常有几十上百帧,这一下按键会覆盖好几帧,导致代码多次执行,随机出不同的动画参数,自然会触发多个动画。

修复步骤

1. 换成单次触发的按键检测

把Input.GetKey改成Input.GetKeyDown,这个API只在按键被按下的第一帧触发一次,不会重复执行:

if (Input.GetKeyDown(KeyCode.C))
{
    int random = Random.Range(1, 3);
    Debug.Log(random);
    anim.SetBool("attacking_" + random.ToString(), true);
}

2. 动画播放完后重置Bool参数

因为用的是Bool类型的动画参数,动画播完后必须把对应的attacking_1/attacking_2设回false,不然下次按C键可能无法再次触发动画(比如上次的参数一直是true,状态机不会重复进入动画状态)。推荐两种简单实现方式:

方式一:用动画事件(最省心)

在动画剪辑的最后一帧添加动画事件,调用脚本里的重置方法:

// 脚本里写这个方法
public void ResetAttackAnim(int attackIndex)
{
    anim.SetBool("attacking_" + attackIndex.ToString(), false);
}

然后打开attacking_1动画剪辑,在时间轴最后一帧右键添加事件,把参数填1;同样给attacking_2动画的最后一帧加事件,参数填2。

方式二:代码检测动画状态

在Update里判断动画是否播放完成,适合不想改动画剪辑的情况:

private int currentAttackIndex = 0; // 记录当前播放的攻击动画索引

void Update()
{
    if (Input.GetKeyDown(KeyCode.C))
    {
        currentAttackIndex = Random.Range(1, 3);
        Debug.Log(currentAttackIndex);
        anim.SetBool("attacking_" + currentAttackIndex.ToString(), true);
    }

    // 检查当前攻击动画是否播放完毕
    if (currentAttackIndex != 0)
    {
        AnimatorStateInfo stateInfo = anim.GetCurrentAnimatorStateInfo(0);
        // 这里的状态名要和你动画状态机里的攻击状态名一致
        if (stateInfo.IsName("attacking_" + currentAttackIndex) && stateInfo.normalizedTime >= 1.0f)
        {
            anim.SetBool("attacking_" + currentAttackIndex.ToString(), false);
            currentAttackIndex = 0;
        }
    }
}

额外提醒

如果你的动画状态机逻辑里,两个攻击状态是互斥的,建议在触发新攻击前,先把两个attacking_的Bool都设为false,避免状态冲突——不过用GetKeyDown加上动画完成后重置的话,这个问题基本不会出现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:57:21