Unity Animator SetTrigger无法自动重置,如何实现动画单次播放?
嘿,先给你纠正一个关键的认知误区:Animator.SetTrigger() 本身并不会在动画播放完成后自动重置触发状态。触发标记一旦被设为true,就会一直保持这个状态——这就是你的Move动画持续循环的核心原因:状态机看到触发标记一直是true,就会反复从Default切换到Move状态。
下面给你几个不用手动检测时机就能实现“调用SetTrigger后动画仅播放一次”的可行方案,按推荐程度排序:
方案1:纯动画状态机配置(零额外代码,最推荐)
这是最省心的实现方式,完全在Unity的Animator窗口里完成配置:
- 首先,确保你的Move状态取消勾选Loop Time(在动画剪辑的Inspector面板里,或者Animator窗口中选中Move状态后,右侧Inspector的Settings里)——这样动画本身只会播放一次。
- 然后,在状态机中添加一条从Move到Default的过渡:
- 这条过渡不需要设置任何条件(把Conditions列表清空)。
- 勾选Has Exit Time,并把Exit Time设为
1(表示动画播放到最后一帧时触发过渡)。 - 把Transition Duration设为
0或者你需要的过渡时长。
- 原来的Default到Move的过渡保持不变,条件设为你的
PlayingTrigger触发。
这样配置后,当你调用SetTrigger(Playing),状态会从Default切到Move,动画播放一次后,因为Exit Time满足,会自动切回Default,而且Animator会在触发过渡完成后自动消耗这个触发标记(也就是把它设为false),完美实现单次播放的需求。
方案2:用动画事件自动重置触发
如果你的状态机结构不适合方案1,或者需要在动画播放到特定节点时重置,可以用动画事件:
- 在Unity的Animation窗口中打开你的Move动画剪辑,在时间轴的最后一帧位置右键,选择Add Event。
- 在你的
TestAnimation脚本中添加一个方法:
public void OnMoveAnimationEnded() { _animation.ResetTrigger(Playing); }
- 选中刚才添加的动画事件,在右侧Inspector的Function下拉框中选择
OnMoveAnimationEnded。
这样动画播放到最后一帧时,会自动调用这个方法重置触发标记,状态机就会自动切回Default(前提是Move到Default的过渡条件是触发标记为false,或者无条件)。
方案3:代码监听动画状态(适合需要额外逻辑的场景)
如果需要在动画结束时执行其他自定义逻辑,可以在代码中监听当前动画状态:
修改你的TestAnimation脚本,添加状态监听逻辑:
private AnimatorStateInfo _currentState; void Update() { if (Input.GetKeyDown(KeyCode.A)) { _animation.SetTrigger(Playing); IDebug.Log("Playing animation "); } // 获取当前基础层的动画状态 _currentState = _animation.GetCurrentAnimatorStateInfo(0); // 判断是否处于Move状态,且动画已经播放完成(normalizedTime >=1),同时动画不循环 if (_currentState.IsName("Move") && _currentState.normalizedTime >= 1f && !_currentState.loop) { _animation.ResetTrigger(Playing); IDebug.Log("Animation finished, trigger reset"); } }
这里要注意,必须确保Move状态的Loop Time是关闭的,否则normalizedTime会一直循环增长,无法判断结束时机。
内容的提问来源于stack exchange,提问作者rootpanthera




