4.3 动画系统:动作节奏的值班表 本节摘要:Animator 状态机是动画版的排班表:每个动画片段是一个班次,过渡条件决定何时换班。本节讲清 Animator 与 Animation Clip 的分工、状态机的搭建规则与参数设计,并演示动画事件与脚本联动、代码控制动画的两条通道。 状态机是动画的排班表 角色在任何时刻都在"演"某一段动作:站着、跑着、跳着。Animator 组件持有 Animator Controller(状态机资产),状态机里有若干状态(State),每个状态绑定一段动画片段(Animation Clip),状态之间用带条件的过渡(Transition)连接。运行时动画岗的任务就是回答一个问题:现在该演哪段、要不要切、怎么接得顺滑。
本节摘要:Animator 状态机是动画版的排班表:每个动画片段是一个班次,过渡条件决定何时换班。本节讲清 Animator 与 Animation Clip 的分工、状态机的搭建规则与参数设计,并演示动画事件与脚本联动、代码控制动画的两条通道。
角色在任何时刻都在"演"某一段动作:站着、跑着、跳着。Animator 组件持有 Animator Controller(状态机资产),状态机里有若干状态(State),每个状态绑定一段动画片段(Animation Clip),状态之间用带条件的过渡(Transition)连接。运行时动画岗的任务就是回答一个问题:现在该演哪段、要不要切、怎么接得顺滑。
用值班室的话说:每个动画片段是一班岗,过渡条件是换班规则,参数(Parameter)是挂在墙上的白板——脚本往白板上写字(设布尔、触发器、浮点),动画岗照白板换班。这个"脚本写白板、状态机读白板"的间接层非常重要:逻辑代码永远不需要知道动画的具体片段名,只汇报事实("我在地面""水平速度 3.2"),换班决策留给状态机。
平台跳跃主角的最小状态集是待机、奔跑、跳跃(跳跃再细分起跳与下落是进阶版)。搭建步骤与设计要点:
背景:把第 3 章的物理角色接上动画,实现三态切换,并在"起跳"瞬间播放音效(动画事件联动)。
操作:角色挂 Animator 与动画片段后,控制脚本只写白板:
using UnityEngine; [RequireComponent(typeof(Animator))] public class AnimBridge : MonoBehaviour { Animator anim; PhysicController controller; // 第 3.2 节的移动脚本 void Awake() { anim = GetComponent<Animator>(); controller = GetComponent<PhysicController>(); } void Update() { // 只汇报事实,不做动画决策 float h = Input.GetAxisRaw("Horizontal"); anim.SetFloat("Speed", Mathf.Abs(h)); bool onGround = controller.IsGrounded; // 移动脚本暴露的只读属性 anim.SetBool("Grounded", onGround); if (Input.GetKeyDown(KeyCode.Space)) { // SetTrigger 用完即焚,状态机消费一次就复位 anim.SetTrigger("Jump"); } } }
在起跳动画片段的关键帧上添加动画事件(Animation Event),回调指向同对象上某脚本的 OnJumpFrame 方法:
// 挂在角色上,供动画事件调用 public class AnimCallbacks : MonoBehaviour { public AudioSource jumpSfx; // 动画事件在时间轴的指定帧触发此方法 public void OnJumpFrame() { if (jumpSfx != null) jumpSfx.Play(); Debug.Log("动画帧事件:起跳瞬间触发"); } }
结果:静止时播待机,按方向键切入奔跑,按空格起跳并听到音效,落地自动接回待机或奔跑;音效精确落在起跳动画的发力帧上,与按键时刻无关。
解读:两段代码对应两种联动通道。Set 系列参数是"持续汇报",每帧写白板,状态机随时读取;动画事件是"帧级回调",由动画时间轴在指定帧反向调用脚本——适合音效、脚步扬尘、攻击判定框开关这类"必须卡在某个动作帧"的逻辑。把攻击伤害判定绑在挥击帧而不是按键帧,就是动画事件最经典的用法。另外注意 SetTrigger 的特性:触发器参数被消费后自动复位,但如果状态机正忙于过渡没消费它,它会一直挂着,导致"下次接地时莫名跳一下"——高频触发的场合可以先 ResetTrigger 再设,或改用布尔加手动复位。
变式:给奔跑加 blendspace(混合树):横轴是速度,纵轴混合走路与跑步两个片段,Speed 参数直接驱动混合权重——状态不变、片段连续渐变,比"走路与跑步两个状态硬切"高级得多,也解释了为什么参数设计要先于状态设计。
进阶话题是动画绑定(Animation Rigging):在动画播放之上叠加一层程序化约束,比如角色手持武器时枪口始终指向目标、视线看向最近敌人——底下的奔跑动画照播,上面的约束层实时修正手臂与头部。它的架构价值在于"动画与逻辑解耦的再进一步":状态机管大动作,绑定层管微对齐,脚本只提供目标点。初学阶段知道有这一层即可,等遇到"动画很对但枪口总差一点"的问题时,它会是你需要的工具。
动作齐了,最后给画面配上表情与声音。下一节 UI、音频与粒子三岗联动。