我重新制作动画系统的思路

最初我想做一个类魂的动作系统。

在 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 更自由。

posted @ 2025-09-09 20:38  Sherryzzzzzzzz  阅读(5)  评论(0)    收藏  举报