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
相关产品推荐
相关产品推荐

