我重新制作动画系统的思路
最初我想做一个类魂的动作系统。
在 Unity 里自然想到使用自带的 Animator,但实际使用时,我觉得它很奇怪:
要用 代码修改 Animator 参数。
Animator 再根据这些参数切换状态,决定播放什么动画。
换句话说,就是 逻辑驱动动画。
但问题来了:
走路时如果我按下 180° 转身,难道还要在逻辑层专门设计一个「Turn180」状态来切换吗?
这显然不符合直觉 —— 逻辑上仍然是 Move 状态,只是动画需要表现一个转身。
后来我在一些文章里看到「用数据直接驱动动画」的思路,这才符合直观的逻辑。于是我打算自己写一个数据驱动的动画机。
Unity 的 Playables API 太麻烦,所以我选择了 Animancer 插件 来做。
这篇文章只是思路分享,也是我做动画机的开发笔记,还不成熟,但希望对有类似困惑的人有帮助。
为什么要分离逻辑层和动画层?
逻辑层:处理玩家输入、角色状态(Idle、Move、Attack、Dodge…)、物理检测(地面、重力等)。
动画层:负责动画表现(Blend Tree、过渡、IK)。
核心原因:
很多动作不能用单一状态来表达(跑步 → 急停 → 转身 → 小步修正)。
如果逻辑层直接驱动 Animator 参数,就会出现:逻辑层瞬间变化 → 动画层慢慢 Blend → 手感怪异。
Unity Animator 的缺点
Animator 的设计是:
逻辑层设置 float Speed、bool IsGrounded → Animator 根据参数切换动画。
问题在于:
逻辑层无法读取动画层的 Blend 状态。逻辑只能“推数值”,完全不知道动画层内部情况。
手感不同步:逻辑 Speed=0,动画还在 Blend → 看起来就不跟手。
扩展性差:AnimatorController 是 Unity 特殊资源,不像代码一样能随意改。
Locomotion vs 攻击/闪避
我认为要分情况:
Locomotion(移动相关)
特点:需要大量混合,属于连续的动作流。
我的做法是 数据驱动动画:
逻辑层计算速度、方向、加速度。
动画层读取这些数据 Blend 动画(Idle ↔ Walk ↔ Run ↔ Turn)。
这样逻辑和动画状态保持一致,避免 “逻辑已停下但动画还在走” 的脱节。
攻击、闪避
特点:离散、独立,需要精确到帧。
我的做法是 逻辑驱动动画:
攻击状态:逻辑决定前摇、判定帧、后摇。
闪避状态:逻辑决定无敌帧、位移距离。
这类动作不需要混合,因此逻辑主导是合理的。
一个对比图
这里用 HTML 表格画一个直观对比:
动作类型 | 驱动方式 | 原因 |
---|---|---|
Locomotion (Idle / Walk / Run / Turn) |
数据驱动动画 | 连续混合,需要平滑过渡。逻辑层产出数值,动画层负责表现。 |
攻击 / 闪避 | 逻辑驱动动画 | 离散动作,需要精确规则控制(前摇、判定帧、无敌帧)。 |
Unity Animator 本质是逻辑推参数 → 动画切换,容易出现逻辑与表现不同步。
总的来说:
Locomotion → 数据驱动动画,保证手感自然。
攻击/闪避 → 逻辑驱动动画,保证规则精确。
Animancer 提供了更灵活的接口,可以让我们自己写逻辑控制动画机,比 Animator 更自由。