61 KiB
Animancer Pro v8.3.0 技术评估与使用手册
版本: Animancer Pro 8.3.0 (2026-03-28)
Unity 要求: 2022.3+
依赖:com.unity.modules.animation
许可: Unity Asset Store EULA
包路径:Packages/com.kybernetik.animancer/
官方文档: https://kybernetik.com.au/animancer/
API 文档: https://kybernetik.com.au/animancer/api/Animancer/
命名空间:Animancer、Animancer.FSM、Animancer.TransitionLibraries
目录
- 概述与设计哲学
- 架构总览
- 核心组件
- 节点层级体系 (Nodes)
- 状态系统 (States)
- Transition 系统
- 事件系统 (Events)
- Fade 与权重系统
- Mixer 状态 (混合树等价)
- 动画层 (Layers)
- Controller State (Mecanim 兼容)
- 内置有限状态机 (FSM)
- 参数系统 (Parameters)
- 高级特性
- Editor 工具链
- 数据类型与工具
- Animancer vs Unity Mecanim 详细对比
- 性能分析
- 与 BaseGames 架构集成方案
- 优缺点总结
- 总结与建议
1. 概述与设计哲学
1.1 什么是 Animancer
Animancer 是基于 Unity Playables API 的动画插件,核心理念:
用代码直接控制动画,不需要 Animator Controller 状态机。
传统 Unity 动画工作流要求在 Animator Controller 中建立状态图(Mecanim),然后通过 SetTrigger/SetBool 间接驱动转换。Animancer 移除这个中间层,让开发者直接在 C# 代码中调用 Play(clip) 播放任何 AnimationClip。
1.2 核心设计原则
| 原则 | 说明 |
|---|---|
| 简洁性 | 一行代码即可播放动画,无需预配置状态图 |
| 透明性 | 所有内部状态均可访问和调试,附带完整源码 |
| 适应性 | 不强制单一组织方式,脚本自由决定动画逻辑 |
| 安全性 | 直接引用 AnimationClip 对象,无魔法字符串 |
| 清晰性 | 字段声明即需求列表 |
| 可靠性 | 始终执行最后一个 Play() 调用,不会吞掉命令 |
1.3 底层实现
Animancer 仍然使用 Unity 底层基础设施:
Animator组件(必须存在于 GameObject 上)PlayableGraph和各种Playable节点AnimationClip资源
它 不需要 的是:
RuntimeAnimatorController资产- Animator 窗口中的状态机图形编辑器
- Animator Parameters、Transitions、Blend Trees 的图形化配置
2. 架构总览
2.1 Playable Graph 层级
PlayableGraph (Unity 底层)
└── AnimancerLayerMixerList (根 Playable — AnimationLayerMixerPlayable)
├── AnimancerLayer[0] (AnimationMixerPlayable)
│ ├── ClipState (AnimationClipPlayable) ── AnimationClip
│ ├── ClipState (AnimationClipPlayable) ── AnimationClip
│ ├── MixerState (AnimationMixerPlayable)
│ │ ├── ClipState ── walk
│ │ └── ClipState ── run
│ └── ControllerState (AnimatorControllerPlayable)
├── AnimancerLayer[1] (AnimationMixerPlayable)
│ └── ClipState ── 上半身覆盖
└── ...更多层 (默认最多 4 层,可扩展)
2.2 核心类关系
AnimancerComponent (MonoBehaviour — 主入口)
├── Animator (Unity 组件引用)
└── AnimancerGraph (核心管理器)
├── PlayableGraph (Unity Playable 图)
├── AnimancerLayerMixerList → AnimancerLayer[]
├── AnimancerStateDictionary (Object → AnimancerState 映射)
├── ParameterDictionary (命名参数池)
├── NamedEventDictionary (命名事件回调)
├── PreUpdatables / PostUpdatables (自定义更新队列)
└── DefaultFadeDuration = 0.25f (静态默认淡入时长)
AnimancerNodeBase (抽象基类)
├── AnimancerGraph (根节点)
└── AnimancerNode (抽象可播放节点)
├── AnimancerLayer (层)
└── AnimancerState (抽象状态基类)
├── ClipState — 单个 AnimationClip
├── ControllerState — RuntimeAnimatorController
├── PlayableAssetState — Timeline PlayableAsset
├── AnimationJobState<T> — 自定义 Animation Job
├── SequenceState — 序列播放
└── ParentState (抽象容器)
├── ManualMixerState — 手动权重混合
└── MixerState<T> — 参数化混合
├── LinearMixerState — 1D 线性混合
└── Vector2MixerState (抽象)
├── CartesianMixerState — 笛卡尔 2D
└── DirectionalMixerState — 极坐标 2D
2.3 数据流
用户代码
→ animancer.Play(ClipTransition)
→ AnimancerGraph.Play()
→ AnimancerStateDictionary.GetOrCreate(transition)
→ transition.CreateState() / transition.Apply(state)
→ AnimancerLayer.Play(state, fadeDuration, fadeMode)
→ FadeGroup 管理权重淡入淡出
→ PlayableGraph 评估 (每帧)
→ Animator 应用骨骼变换
2.4 完整目录结构 (171 个源文件)
Packages/com.kybernetik.animancer/
├── Runtime/ # 171 个源文件
│ ├── AnimancerComponent.cs # 主入口 MonoBehaviour
│ ├── HybridAnimancerComponent.cs # Animator Controller + Animancer 混合
│ ├── NamedAnimancerComponent.cs # 命名动画组件
│ ├── SoloAnimation.cs # 单动画精简组件
│ ├── Core/
│ │ ├── AnimancerGraph.cs # 核心 Playable 图管理器
│ │ ├── AnimancerLayerList.cs # 层列表抽象
│ │ ├── AnimancerLayerMixerList.cs # 层混合器
│ │ ├── AnimancerStateDictionary.cs # 状态注册表
│ │ ├── AnimancerUtilities.cs # 扩展方法
│ │ ├── UpdatableListPlayable.cs # 自定义 Playable
│ │ ├── Events/ (9 文件) # 事件系统
│ │ │ ├── AnimancerEvent.cs
│ │ │ ├── AnimancerEvent.Sequence.cs
│ │ │ ├── AnimancerEvent.Dispatcher.cs
│ │ │ ├── AnimancerEvent.Invoker*.cs (3 种)
│ │ │ ├── AnimancerEvent.Invocation.cs
│ │ │ ├── AnimancerState.Events.cs
│ │ │ ├── NamedEventDictionary.cs
│ │ │ └── Invokables/ (Parameter<T>, UnityEvent 等)
│ │ ├── Fades/ (2 文件)
│ │ │ ├── FadeGroup.cs # 权重淡入淡出管理
│ │ │ └── NodeWeight.cs # 节点权重
│ │ ├── Nodes/ (10 文件) # 状态层级
│ │ │ ├── AnimancerNodeBase.cs
│ │ │ ├── AnimancerNode.cs
│ │ │ ├── AnimancerState.cs + ExpectFade.cs
│ │ │ ├── AnimancerLayer.cs
│ │ │ ├── ClipState.cs
│ │ │ ├── ParentState.cs
│ │ │ ├── PlayableAssetState.cs
│ │ │ ├── SequenceState.cs
│ │ │ └── AnimationJobState.cs
│ │ └── Weighted Mask Layers/ (4 文件)
│ │ ├── WeightedMaskLayers.cs
│ │ ├── WeightedMaskLayersDefinition.cs
│ │ ├── WeightedMaskLayerList.cs
│ │ └── WeightedMaskMixerJob.cs
│ ├── Controller States/ (2 文件)
│ │ ├── ControllerState.cs
│ │ └── ControllerState.ParameterBinding.cs
│ ├── Mixer States/ (7 文件)
│ │ ├── ManualMixerState.cs
│ │ ├── MixerStateT.cs
│ │ ├── LinearMixerState.cs
│ │ ├── Vector2MixerState.cs
│ │ ├── CartesianMixerState.cs
│ │ ├── DirectionalMixerState.cs
│ │ └── NodeParameter.cs
│ ├── Data Types/ (15 文件)
│ │ ├── FadeMode.cs
│ │ ├── StringReference.cs / StringAsset.cs
│ │ ├── Updatable.cs / FastEnumerator.cs / IndexedList.cs
│ │ ├── Parameters/ (6 文件)
│ │ │ ├── ParameterDictionary.cs
│ │ │ ├── Parameter.cs
│ │ │ ├── SmoothedFloatParameter.cs
│ │ │ └── SmoothedVector2Parameter.cs
│ │ └── Object Pooling/ (6 文件)
│ │ ├── ObjectPool<T>.cs
│ │ ├── ListPool / DictionaryPool / SetPool / CollectionPool
│ │ └── StringBuilderPool
│ ├── Interfaces/ (16 文件)
│ │ IAnimancerComponent, ITransition, IState, IMotion,
│ │ IUpdatable, IHasKey, IHasEvents, IHasDescription,
│ │ ICloneable<T>, ICopyable<T>, IConvertable<T>,
│ │ ICharacterRoot, IPolymorphic, IWrapper, IInitializable, IInvokable
│ └── Utilities/
│ ├── Transitions/ (25 文件)
│ │ ├── Transition.cs (基类)
│ │ ├── TransitionAsset.cs / TransitionAssetBase.cs / TransitionAssetT.cs
│ │ ├── TransitionAssetReference.cs
│ │ ├── Transition Types/
│ │ │ ├── ClipTransition.cs
│ │ │ ├── ClipTransitionSequence.cs
│ │ │ ├── ControllerTransition.cs
│ │ │ ├── PlayableAssetTransition.cs
│ │ │ ├── ManualMixerTransition.cs
│ │ │ ├── LinearMixerTransition.cs
│ │ │ ├── MixerTransition2D.cs
│ │ │ └── TransitionSequence.cs
│ │ └── Transition Libraries/ (6 文件)
│ │ ├── TransitionLibrary.cs
│ │ ├── TransitionLibraryAsset.cs
│ │ ├── TransitionLibraryDefinition.cs
│ │ ├── TransitionModifierDefinition.cs
│ │ └── NamedIndex.cs
│ ├── FSM/ (12 文件)
│ │ ├── IState.cs
│ │ ├── StateMachine1.cs + WithDefault + InputBuffer + StateSelector
│ │ ├── StateMachine2.cs + WithDefault + InputBuffer
│ │ ├── StateBehaviour.cs
│ │ ├── DelegateState.cs
│ │ ├── StateChange.cs / KeyChange.cs
│ │ └── StateMachineUtilities.cs
│ ├── Animation Jobs/ (5 文件)
│ │ AnimancerJob, AnimatedBool/Int/Float, AnimatedProperty
│ ├── Custom Fade/ (4 文件)
│ │ Easing.cs, DontAllowFade.cs, FadeGroupExtensions.cs,
│ │ MixerChildFade.cs
│ ├── Directional Animations/ (10 文件)
│ │ DirectionalAnimations3D, DirectionalAnimationSet2/4/8,
│ │ DirectionalClipTransition, Directions
│ ├── Redirect Root Motion/ (4 文件)
│ │ RedirectRootMotion (base), →Transform, →Rigidbody,
│ │ →CharacterController
│ └── TimeSynchronizer.cs, SpriteRendererTextureSwap.cs,
│ ExitEvent.cs, PlayableOutputRefresher.cs,
│ ExposedPropertyTable.cs
├── Editor/ # 编辑器工具
│ ├── Animancer Tools/ (窗口工具集)
│ ├── Transition Libraries/ (可视化编辑)
│ ├── Transition Previews/ (动画预览)
│ ├── Previews/
│ ├── GUI/ (Inspector 自定义绘制)
│ ├── Caching/ (编辑器缓存)
│ └── Serialization/
├── Samples~/ (示例场景)
│ ├── 01 Basics/
│ ├── 02 Fine Control/
│ ├── 03 Mixers/
│ ├── 04 Layers/
│ ├── 05 Events/
│ ├── 06 State Machines/
│ ├── 07 Sprites/
│ ├── 08 Animator Controllers/
│ ├── 09 Inverse Kinematics/
│ ├── 10 Animation Jobs/
│ └── Code/ (共用代码)
└── Art/ (示例美术资源)
3. 核心组件
3.1 AnimancerComponent
主入口组件,挂载在拥有 Animator 的 GameObject 上。
[AddComponentMenu("Animancer/Animancer Component")]
[DefaultExecutionOrder(-5000)]
public class AnimancerComponent : MonoBehaviour,
IAnimancerComponent, IEnumerator, IAnimationClipSource, IAnimationClipCollection
{
// ─── 核心引用 ───
[SerializeField] private Animator _Animator;
public AnimancerGraph Graph { get; } // 惰性初始化
// ─── 播放接口 ───
AnimancerState Play(AnimationClip clip);
AnimancerState Play(AnimationClip clip, float fadeDuration);
AnimancerState Play(ITransition transition);
AnimancerState Play(ITransition transition, float fadeDuration, FadeMode fadeMode);
// ─── 便捷访问 ───
AnimancerLayerList Layers { get; } // 动画层列表
AnimancerStateDictionary States { get; } // 状态注册表
ParameterDictionary Parameters { get; } // 参数字典
NamedEventDictionary Events { get; } // 命名事件字典
TransitionLibraryAsset Transitions { get; } // 转换库 (Pro)
// ─── 生命周期 ───
AnimatorUpdateMode UpdateMode { get; set; }
DisableAction ActionOnDisable { get; set; } // 禁用时行为
bool IsGraphPlaying { get; set; }
// ─── 实用方法 ───
void Stop();
void Destroy();
}
DisableAction 枚举:
| 值 | 行为 |
|---|---|
Stop |
停止并重置,保留当前值 |
Pause |
暂停以便后续恢复 |
Continue |
非激活时继续播放 |
Reset |
停止并重新绑定 Animator |
Destroy |
完全销毁 PlayableGraph |
关键设计点:
- 自动在
OnEnable初始化AnimancerGraph - 在
OnDisable根据ActionOnDisable处理图 - 不需要
RuntimeAnimatorController Play()返回AnimancerState,允许链式操作- 支持
yield等待所有动画完成
3.2 HybridAnimancerComponent (Pro)
允许同时使用 Animator Controller 和 Animancer。主 Controller 作为 Layer 0 的默认状态,可以在其上叠加 Animancer 播放的单独 Clips。
用途:渐进式迁移 — 保留现有 Animator Controller,逐步将状态迁移到纯代码驱动。
3.3 NamedAnimancerComponent
通过字符串名称注册和查找动画:
public class NamedAnimancerComponent : AnimancerComponent
{
[SerializeField] private StringAsset[] _Names; // v8.3 新增:可选自定义名称
[SerializeField] private AnimationClip[] _Animations;
// Awake 中将所有 clip 注册到字典,可通过名称查找
// 若 _Names[i] 非空,则以 StringAsset 作为键;否则回退到 clip.name
}
3.4 SoloAnimation
最简化组件 — 只播放一个动画,替代 Animator + Controller 的最小配置:
public class SoloAnimation : MonoBehaviour
{
[SerializeField] private Animator _Animator;
[SerializeField] private AnimationClip _Clip;
[SerializeField] private float _Speed = 1;
}
4. 节点层级体系 (Nodes)
4.1 AnimancerNodeBase (抽象根基类)
所有 Playable 节点的基础。
| 属性 | 类型 | 说明 |
|---|---|---|
Graph |
AnimancerGraph |
父图 |
Parent |
AnimancerNodeBase |
父节点 |
Layer |
AnimancerLayer |
所属层 |
ChildCount |
int |
子节点数量 |
Playable |
Playable |
Unity Playable 包装 |
BaseWeight |
float |
权重贡献 (0–1) |
Speed |
float |
播放速度 |
EffectiveSpeed |
float |
含父节点乘积的最终速度 |
KeepChildrenConnected |
bool |
性能优化标志 |
ApplyAnimatorIK |
bool |
Humanoid IK 支持 |
ApplyFootIK |
bool |
脚部 IK 支持 |
4.2 AnimancerNode (抽象可播放节点)
在 NodeBase 基础上增加:
| 属性/方法 | 说明 |
|---|---|
Index |
在父节点端口索引 |
FadeGroup |
淡入淡出管理器 |
CreatePlayable(out Playable) |
抽象方法,创建底层 Playable |
DestroyPlayable() |
销毁 Playable |
RecreatePlayable() |
重建 Playable |
CopyFrom(AnimancerNode, CloneContext) |
深拷贝 |
ConnectChildUnsafe(int, AnimancerNode) |
快速连接 |
DisconnectChildSafe(int) |
安全断开 |
IEnumerator 支持 |
可 yield 等待 |
5. 状态系统 (States)
5.1 AnimancerState (抽象基类)
所有可播放动画单元的基类,核心 API:
public abstract class AnimancerState : AnimancerNode
{
// ─── 身份 ───
object Key { get; set; } // 注册表中的键
AnimancerLayer Layer { get; } // 所属层
AnimationClip Clip { get; } // 动画片段 (ClipState)
Object MainObject { get; } // 主资产引用
GameObject GameObject { get; } // 目标 GameObject
// ─── 时间控制 ───
float Time { get; set; } // 当前时间(秒)
double TimeD { get; set; } // 双精度时间
float NormalizedTime { get; set; } // 归一化时间 [0,1]
double RawTime { get; set; } // 原始时间
float RemainingDuration { get; } // 剩余时长
float Length { get; } // 动画总长度
bool IsLooping { get; } // 是否循环
// ─── 播放控制 ───
float Speed { get; set; } // 播放速度
float Weight { get; set; } // 混合权重 [0,1]
bool IsPlaying { get; set; } // 是否正在播放
bool IsActive { get; } // 权重 > 0
// ─── 事件 ───
AnimancerEvent.Sequence Events { get; } // 事件序列
AnimancerEvent.Sequence SharedEvents { get; set; }
// ─── Root Motion ───
Vector3 AverageVelocity { get; }
// ─── 方法 ───
void Play() / void Stop() / void Pause();
void Fade(float targetWeight, float? fadeDuration);
void Destroy();
void SetParent(AnimancerNode parent);
// ─── 关键 Pro 特性 ───
float ExpectFade { get; set; } // 预期淡入时长
int LayerIndex { get; } // 层索引
}
5.2 ClipState
最常用的状态类型 — 播放单个 AnimationClip:
public sealed class ClipState : AnimancerState
{
public AnimationClip Clip { get; }
// 内部创建 AnimationClipPlayable
// 支持所有 Rig 类型:Humanoid, Generic, Sprite
}
5.3 PlayableAssetState (Pro)
包装 PlayableAsset (Timeline) 作为 Animancer 图中的一个节点,可与其他状态混合:
animancer.Play(myTimelineTransition);
// Timeline 作为普通 AnimancerState 参与权重混合
5.4 SequenceState (Pro)
按顺序播放一系列子状态,支持子状态间淡入时间:
public class SequenceState : ParentState, IUpdatable
{
void Set(params ITransition[] transitions);
float Length { get; } // 所有子动画总长度
}
5.5 AnimationJobState (Pro)
运行自定义 IAnimationJob,实现程序化动画:
public interface IAnimancerStateJob : IDisposable
{
float Length { get; }
bool IsLooping { get; }
void ProcessRootMotion(AnimationStream stream, double time);
void ProcessAnimation(AnimationStream stream, double time);
}
public class AnimationJobState<T> : AnimancerState, IUpdatable
where T : struct, IAnimancerStateJob
{
public T Job { get; set; }
}
5.6 AnimancerStateDictionary
状态注册表,映射键到状态:
public class AnimancerStateDictionary
{
ClipState Create(AnimationClip clip);
ClipState Create(object key, AnimationClip clip);
AnimancerState GetOrCreate(ITransition transition);
AnimancerState Get(object key);
bool TryGet(object key, out AnimancerState state);
AnimancerState Current { get; } // Layer 0 当前状态
void Register(AnimancerState state);
void Unregister(AnimancerState state);
// ─── v8.3 新增 ───
bool TryGetAlias(object key, out AnimancerState state); // 优先通过 TransitionLibrary 别名查找
bool TryGetAlias(IHasKey hasKey, out AnimancerState state);
}
TryGetAlias (v8.3):先查 TransitionLibrary 是否将 key 映射为别名,再用最终键查找状态。AnimancerGraph.IsPlaying 内部已改用此方法,使得通过 Library 别名也能正确判断播放状态。
Key 可以是: AnimationClip、clip.name(字符串)、int、enum、自定义对象、IHasKey 实现。
6. Transition 系统
Transition 是 Animancer 的核心数据架构层,将动画播放参数封装为可序列化配置对象。
6.1 ITransition 接口
public interface ITransition : IHasKey
{
float FadeDuration { get; set; }
FadeMode FadeMode { get; }
AnimancerState CreateState();
void Apply(AnimancerState state);
bool IsValid { get; }
bool IsLooping { get; }
float NormalizedStartTime { get; set; } // NaN = 不设置
float MaximumLength { get; }
float Speed { get; set; }
object Key { get; }
AnimancerEvent.Sequence Events { get; }
}
6.2 Transition 四级体系
| 级别 | 类型 | 序列化方式 | 适用场景 |
|---|---|---|---|
| Level 0 | AnimationClip |
直接引用 | 最简单,无参数配置 |
| Level 1 | ClipTransition |
[SerializeField] 字段 |
按实例配置,含 FadeDuration/Speed/Events |
| Level 2 | TransitionAsset (SO) |
ScriptableObject 资产 | 跨脚本/跨角色共享 |
| Level 3 | TransitionLibrary (SO) |
ScriptableObject 资产 | 集中管理 + 转换修正器 |
6.3 ClipTransition
最常用的 Transition 类型:
[Serializable]
public class ClipTransition : Transition<ClipState>, IMotion, IAnimationClipCollection
{
[SerializeField] private AnimationClip _Clip;
[SerializeField] private float _NormalizedStartTime;
// 继承自 Transition<T>:
// float FadeDuration, float Speed, AnimancerEvent.Sequence Events
public override ClipState CreateState() => new ClipState(_Clip);
public float Length { get; }
public Vector3 AverageVelocity { get; } // Root Motion
public float AverageAngularSpeed { get; }
}
6.4 TransitionAsset (ScriptableObject)
[CreateAssetMenu(menuName = "Animancer/Transition Asset")]
public class TransitionAsset : TransitionAsset<ITransition>
{
// 可在 Project 窗口右键创建
// 多角色共享同一配置
// 注意:Events 不应存储在共享 Asset 上
// 正确做法:state.Events(this).OnEnd ??= callback
}
6.5 TransitionLibraryAsset (Pro)
[CreateAssetMenu(menuName = "Animancer/Transition Library")]
public class TransitionLibraryAsset : ScriptableObject
{
// 集中管理角色的所有 Transition
// 支持 Modifier:A → B 时使用特殊淡入参数
// 类似 Animator Controller 的转换表
}
用途:当同一个"攻击"动画从"idle"进入和从"run"进入需要不同淡入时长时。
内部组件:
TransitionLibrary— 运行时查找TransitionLibraryDefinition— 编辑器定义TransitionModifierDefinition— 转换修正器NamedIndex— 按名称索引
v8.3 新增功能:
| 特性 | 说明 |
|---|---|
| 分组 (Grouping) | 可将 Transition 按逻辑分组(如移动/战斗/特殊),在编辑器窗口中折叠/展开,大型 Library 组织更清晰 |
| Normalized Start Time 编辑 | 修正器现可同时覆盖 Fade Duration 和 Normalized Start Time |
| Edit 按钮 | Inspector 中 TransitionLibraryAsset 字段新增 Edit 按钮,一键跳转到 Library 编辑窗口 |
| 改进的 Remove | Remove Transition 按钮支持单独移除修正器或整个分组 |
6.6 其他 Transition 类型
| 类型 | 说明 |
|---|---|
ControllerTransition |
包装 RuntimeAnimatorController |
LinearMixerTransition |
1D 混合(走→跑) |
MixerTransition2D |
2D 混合(八方向移动) |
ManualMixerTransition |
手动权重混合 |
PlayableAssetTransition |
Timeline PlayableAsset |
TransitionSequence |
串联多个 Transition |
ClipTransitionSequence |
串联多个 ClipTransition(连招) |
6.7 FadeMode 枚举
| FadeMode | 行为 | 适用场景 |
|---|---|---|
FixedSpeed (默认) |
淡入速度固定,半途开始则更快完成 | 通用默认 |
FixedDuration |
淡入时长固定,不论起始权重 | 需要可预测时长 |
FromStart |
克隆状态从头播放,旧状态同时淡出 | 同动画中断自身(连续攻击) |
NormalizedSpeed |
FixedSpeed × 动画时长 | 与动画长度成比例 |
NormalizedDuration |
FixedDuration × 动画时长 | 与动画长度成比例 |
NormalizedFromStart |
FromStart × 动画时长 | 与动画长度成比例 |
7. 事件系统 (Events)
7.1 AnimancerEvent 结构
public partial struct AnimancerEvent
{
public float normalizedTime; // 触发时间 [0,1]
public Action callback; // 回调委托
// 特殊常量
public const float AlmostOne = 0.99999994f; // 循环动画末尾事件
// 参数化事件
public static void Parametize<T>(Action<T> callback);
public static T GetCurrentParameter<T>();
}
7.2 AnimancerEvent.Sequence
public class Sequence : IEnumerable<AnimancerEvent>
{
int Count { get; }
AnimancerEvent this[int index] { get; set; }
// 末尾事件(一等公民)
ref AnimancerEvent EndEvent { get; }
float NormalizedEndTime { get; set; }
Action OnEnd { get; set; }
// 操作
void Add(float normalizedTime, Action callback);
void Invoke(AnimancerState state);
// ─── v8.3 新增:IndexOf 系列 ───
int IndexOf(StringReference name, int startIndex = 0); // 按名称查找
int IndexOfRequired(StringReference name, int startIndex = 0); // 按名称查找(未找到抛异常)
int IndexOf(AnimancerEvent animancerEvent); // 按事件查找
int IndexOf(float normalizedTime); // 按时间查找
int IndexOf(int indexHint, float normalizedTime); // 带提示的按时间查找
}
7.3 事件绑定模式
关键 API: state.Events(owner) — 获取/创建绑定到特定 owner 的本地事件副本。
// ✅ 推荐写法:幂等事件绑定
AnimancerState state = _Animancer.Play(_Action);
state.Events(this).OnEnd ??= OnActionEnd; // ??= 保证只赋值一次
// ❌ 错误写法:每次重新赋值导致 GC
state.Events(this).OnEnd = OnActionEnd; // 每次新建 delegate
this 参数的作用:
- 将事件绑定到该组件的生命周期
- 组件销毁时自动清理事件
- 同一 State 可被不同组件绑定不同事件
7.4 命名事件系统
public class NamedEventDictionary
{
void Register(string name, Action callback);
void Unregister(string name, Action callback);
void Invoke(string name);
}
7.5 事件调度架构
| 组件 | 职责 |
|---|---|
AnimancerEvent.Dispatcher |
简化事件触发接口 |
AnimancerEvent.Invocation |
执行上下文(State、EventIndex、NormalizedTime、FrameID) |
AnimancerEvent.InvokerFixed |
固定速度事件触发器 |
AnimancerEvent.InvokerDynamic |
动态速度事件触发器 |
AnimancerEvent.Parameter<T> |
类型安全的参数化事件 |
AnimancerEvent.ParameterBoxed |
Object 类型参数事件 |
7.6 与 Unity Animation Events 对比
| 特性 | Unity Animation Events | Animancer Events |
|---|---|---|
| 配置方式 | Animation 窗口可视化 | 代码或 Inspector (ClipTransition) |
| 触发精度 | 依赖帧率,可能跳过 | 精确检测时间范围 |
| 回调类型 | 特定签名方法 | 标准 Action 委托 |
| 参数传递 | int/float/string/Object | 闭包捕获任意数据 |
| 生命周期 | 绑定到 Clip 资源 | 绑定到 State 实例 |
| End 事件 | 不原生支持 | OnEnd 一等公民 |
| 调试性 | 难以调试 | 可断点、可日志 |
8. Fade 与权重系统
8.1 FadeGroup
管理状态间权重淡入淡出的核心类。
public class FadeGroup
{
float FadeSpeed { get; set; }
float RemainingFadeTime { get; }
// 自定义缓动
void SetEasing(Func<float, float> easing);
void SetEasing(Easing.Function function);
}
8.2 自定义 Fade 缓动
AnimancerState state = animancer.Play(clip, 0.25f);
// 预设缓动函数
state.FadeGroup.SetEasing(Easing.Sine.InOut);
// 自定义 lambda
state.FadeGroup.SetEasing(t => t * t);
// 支持的预设缓动族:
// Quadratic, Cubic, Quartic, Quintic, Sine,
// Exponential, Circular, Back, Bounce, Elastic
// 每族含 In, Out, InOut 三种
8.3 NodeWeight
控制单个节点权重更新逻辑,是 FadeGroup 的内部基础。
8.4 DontAllowFade
标记组件,阻止 Sprite 动画淡入淡出(像素风不适合渐变):
[AddComponentMenu("Animancer/Don't Allow Fade")]
public class DontAllowFade : MonoBehaviour { }
8.5 MixerChildFade
Mixer 子状态的特殊淡入行为控制。
9. Mixer 状态 (混合树等价)
Mixer 是 Animancer 中替代 Mecanim Blend Tree 的方案(全部 Pro-Only)。
9.1 Mixer 类型对照表
| Animancer Mixer | Mecanim Blend Tree | 参数类型 | 说明 |
|---|---|---|---|
LinearMixerState |
1D Blend | float |
按单轴参数线性混合 |
CartesianMixerState |
2D Freeform Cartesian | Vector2 |
笛卡尔坐标插值 |
DirectionalMixerState |
2D Freeform Directional | Vector2 |
极坐标梯度带插值 |
ManualMixerState |
Direct Blend | 手动权重 | 直接控制每个子状态权重 |
9.2 ManualMixerState (手动混合)
public class ManualMixerState : ParentState, ICopyable, IParametizedState, IUpdatable
{
// 子状态管理
void Add(AnimancerState state);
void Set(int index, AnimancerState state);
void Remove(AnimancerState state);
void SetChildWeight(int index, float weight);
// 属性
AnimancerState[] ChildStates { get; }
int ChildCount { get; }
float Length { get; } // 加权平均时长
// 同步
void GetSynchronizedChildren(); // 获取同步子集
void RecalculateWeights(); // 重新计算混合权重
}
9.3 MixerState (参数化混合基类)
public abstract class MixerState<T> : ManualMixerState
{
T Parameter { get; set; } // 驱动参数
T NormalizedParameter { get; set; } // 归一化参数
T[] Thresholds { get; } // 阈值数组
// 子类实现
abstract void CalculateWeights(); // 混合权重算法
// 参数绑定
StringReference ParameterName { get; set; } // 绑定到 ParameterDictionary
}
9.4 LinearMixerState (1D 混合)
public class LinearMixerState : MixerState<float>
{
float MinThreshold { get; }
float MaxThreshold { get; }
bool ExtrapolateSpeed { get; set; } // 参数超阈值时自动加速
void Add(AnimancerState state, float threshold);
void AssertThresholdsSorted();
}
用法示例:
[SerializeField] private LinearMixerTransition _moveBlend;
// Inspector 配置: Idle(0) → Walk(0.5) → Run(1.0)
var state = animancer.Play(_moveBlend);
((LinearMixerState)state).Parameter = moveSpeed; // 实时更新
9.5 Vector2MixerState (2D 混合)
public abstract class Vector2MixerState : MixerState<Vector2>
{
float ParameterX { get; set; }
float ParameterY { get; set; }
StringReference ParameterNameX { get; set; }
StringReference ParameterNameY { get; set; }
}
CartesianMixerState — 笛卡尔坐标插值,适合前进/侧移。
DirectionalMixerState — 极坐标梯度带插值(Polar Gradient Band),比 Mecanim 更精确,适合八方向移动。
9.6 NodeParameter (参数绑定)
自动将 Mixer 参数同步到全局 ParameterDictionary:
var mixer = new LinearMixerState();
mixer.ParameterName = "Speed";
// 自动绑定到 graph.Parameters["Speed"]
// 外部修改 Parameters["Speed"] 时 mixer 自动重算权重
9.7 Mixer vs Blend Tree
| 特性 | Mecanim Blend Tree | Animancer Mixer |
|---|---|---|
| 配置方式 | Animator 窗口图形化 | 代码或 Inspector |
| 动态修改 | 不支持运行时修改结构 | 可运行时添加/移除/替换子状态 |
| 嵌套 | 可嵌套 | 可嵌套 |
| 参数驱动 | Animator Parameters | 直接属性或 ParameterDictionary |
| 同步 | 有限 | TimeSynchronizer 完整同步 |
| 调试 | 不可视化权重 | Inspector 实时显示 |
10. 动画层 (Layers)
10.1 AnimancerLayer
public sealed class AnimancerLayer : AnimancerNode
{
// ─── 状态管理 ───
AnimancerState CurrentState { get; }
IReadOnlyList<AnimancerState> ActiveStates { get; }
// ─── 混合模式 ───
bool IsAdditive { get; set; } // 叠加 vs 覆盖
AvatarMask Mask { get; set; } // 骨骼遮罩
float Weight { get; set; } // 层权重
// ─── IK ───
bool ApplyAnimatorIK { get; set; }
bool ApplyFootIK { get; set; }
// ─── 方法 ───
AnimancerState Play(ITransition transition);
AnimancerState Play(AnimancerState state, float fadeDuration, FadeMode fadeMode);
AnimancerState GetOrCreateState(ITransition transition);
void Stop() / void Pause();
// ─── 查询 ───
int ChildCount { get; }
int CommandCount { get; } // 状态变更计数器
Vector3 AverageVelocity { get; } // 加权平均速度
}
10.2 AnimancerLayerList
public abstract class AnimancerLayerList : IEnumerable<AnimancerLayer>
{
int Count { get; }
static int DefaultCapacity { get; } // 默认 4 层
AnimancerLayer this[int index] { get; } // 自动创建
AnimancerLayer Add();
void SetMinCount(int min);
bool IsAdditive(int index);
void SetAdditive(int index, bool value);
AvatarMask GetMask(int index);
void SetMask(int index, AvatarMask mask);
}
10.3 Weighted Mask Layers (高级骨骼权重控制)
标准 AvatarMask 只能做 0/1 二值遮罩。WeightedMaskLayers 支持每骨骼浮点权重:
[AddComponentMenu("Animancer/Weighted Mask Layers")]
public class WeightedMaskLayers : MonoBehaviour
{
[SerializeField] private AnimancerComponent _Animancer;
[SerializeField] private WeightedMaskLayersDefinition _Definition;
[SerializeField] private int _LayerCount = 2;
}
| 组件 | 职责 |
|---|---|
WeightedMaskLayers |
主控组件 |
WeightedMaskLayersDefinition |
SO 定义(权重组配置) |
WeightedMaskLayerList |
动态遮罩列表 |
WeightedMaskMixerJob |
IAnimationJob 实现逐骨骼混合 |
实现原理:使用 IAnimationJob + NativeArray<float> 逐骨骼混合权重。
v8.3 新增 — Root Motion 权重:每层可独立设置 Root Motion 影响权重,WeightedMaskLayersDefinition 新增 RootMotionWeights 数组,WeightedMaskMixerJob 通过 NativeArray<float> rootMotionWeights 逐层混合 Root Motion 输出。适用于上半身覆盖层不影响角色位移的场景。
10.4 层使用示例
// 基础层(0) — 全身动画
animancer.Layers[0].Play(walkTransition);
// 上半身覆盖层(1) — 边走边射击
animancer.Layers[1].Play(shootTransition);
animancer.Layers[1].Mask = upperBodyMask; // AvatarMask
animancer.Layers[1].Weight = 1f;
animancer.Layers[1].IsAdditive = false; // 覆盖模式
11. Controller State (Mecanim 兼容)
11.1 ControllerState (Pro)
包装一个完整的 RuntimeAnimatorController 作为 Animancer 图中的一个节点:
public class ControllerState : AnimancerState, ICopyable, IParametizedState, IUpdatable
{
RuntimeAnimatorController Controller { get; }
AnimatorControllerPlayable Playable { get; }
// 层管理
int LayerCount { get; }
float GetLayerWeight(int layer) / SetLayerWeight(int, float);
void GetLayerAvatarMask(int) / SetLayerAvatarMask();
// Animator 参数
void SetBool(string, bool) / GetBool();
void SetFloat(string, float) / GetFloat();
void SetInteger(string, int) / GetInteger();
void Trigger(string name);
// 停止行为配置
int[] DefaultStateHashes { get; }
ActionOnStop[] ActionsOnStop { get; }
enum ActionOnStop { DefaultState, RewindTime, Continue }
}
11.2 ControllerState.ParameterBinding
将 Controller 参数绑定到 Animancer 的 ParameterDictionary,双向同步。
12. 内置有限状态机 (FSM)
Animancer 附带一个与动画完全独立的通用 FSM 系统,位于 Animancer.FSM 命名空间。
12.1 IState 接口
public interface IState
{
bool CanEnterState { get; } // 进入守卫
bool CanExitState { get; } // 退出守卫
void OnEnterState(); // 进入回调
void OnExitState(); // 退出回调
}
// 扩展接口 — 状态知道自己属于哪个状态机
public interface IOwnedState<TState> : IState
{
StateMachine<TState> OwnerStateMachine { get; }
}
12.2 StateMachine<TState> (无键状态机)
public class StateMachine<TState> where TState : class, IState
{
TState CurrentState { get; }
TState PreviousState { get; }
TState NextState { get; }
// 四种切换策略
bool CanSetState(TState state); // 检查能否切换(两端守卫)
bool TrySetState(TState state); // 尊重守卫,已在该状态则跳过
bool TryResetState(TState state); // 尊重守卫,允许重入自身
void ForceSetState(TState state); // 强制切换(忽略守卫)
// 默认状态支持 (WithDefault 嵌套类)
TState DefaultState { get; set; }
bool TrySetDefaultState();
void ForceSetDefaultState();
}
12.3 StateMachine<TKey, TState> (带键状态机)
public class StateMachine<TKey, TState> : StateMachine<TState>
where TState : class, IState
{
TKey CurrentKey { get; }
void Register(TKey key, TState state);
TState GetState(TKey key);
bool TryGetState(TKey key, out TState state);
bool TrySetState(TKey key);
bool TryResetState(TKey key);
void ForceSetState(TKey key);
}
12.4 StateBehaviour
MonoBehaviour 基类,用 OnEnable()/OnDisable() 映射状态进出:
public abstract class StateBehaviour : MonoBehaviour, IOwnedState
{
// OnEnable() → 进入状态(Enable 组件)
// OnDisable() → 退出状态(Disable 组件)
public virtual bool CanEnterState => true;
public virtual bool CanExitState => true;
}
12.5 DelegateState
Lambda 快速创建状态:
var state = new DelegateState(
canEnter: () => true,
onEnter: () => Debug.Log("Enter"),
onExit: () => Debug.Log("Exit")
);
12.6 InputBuffer
解决"动作不可中断时输入会丢失"的问题:
public class InputBuffer
{
void Buffer(TState state, float timeout); // 缓冲一个输入
void Update(); // 每帧检查能否执行
// 在 timeout 内反复 TrySetState,成功则消耗缓冲
}
12.7 StateChange / KeyChange
转换上下文结构,在切换过程中提供 PreviousState/NextState 信息:
using (new StateChange<T>(machine, previousState, nextState))
{
previousState.OnExitState();
nextState.OnEnterState();
}
12.8 FSM 使用架构
Character (MonoBehaviour, hub)
├── AnimancerComponent — 动画
├── StateMachine<CharacterState>.WithDefault — 状态机
└── Equipment / HealthPool — 数据
CharacterState (StateBehaviour, 基类)
├── IdleState — 默认状态
├── MoveState — 移动
├── ActionState — 攻击/技能
└── ...
Brain (MonoBehaviour, 输入驱动)
├── PlayerBrain — 玩家输入
└── AIBrain — AI 行为
13. 参数系统 (Parameters)
13.1 ParameterDictionary
全局命名参数字典,供 Mixer 自动绑定:
// 写入
animancer.Parameters.Set<float>("Speed", 5f);
// 读取
float speed = animancer.Parameters.Get<float>("Speed").Value;
// 尝试读取
if (animancer.Parameters.TryGet<float>("Speed", out var param))
Debug.Log(param.Value);
13.2 Parameter<T>
泛型参数,支持变更事件:
public class Parameter<T>
{
T Value { get; set; }
StringReference Key { get; }
Type ValueType { get; }
event Action<T> OnValueChanged;
}
13.3 SmoothedFloatParameter / SmoothedVector2Parameter
平滑参数,自动插值到目标值:
public class SmoothedFloatParameter
{
float TargetValue { get; set; }
float CurrentValue { get; }
void Update(float deltaTime); // 每帧平滑
}
13.4 StringReference / StringAsset
轻量字符串引用,用于参数键和事件名:
StringReference— 运行时字符串唯一化包装StringAsset— ScriptableObject 容器,可在 Inspector 中引用
14. 高级特性
14.1 Directional Animations (方向动画)
支持 2D/4D/8D 方向动画集:
// 2方向(左/右)
[SerializeField] private DirectionalAnimationSet2 _walk2;
// 4方向(上/下/左/右)
[SerializeField] private DirectionalAnimationSet4 _walk4;
// 8方向
[SerializeField] private DirectionalAnimationSet8 _walk8;
// 3D 版本(根据 Vector3 方向选择)
[SerializeField] private DirectionalAnimations3D _walk3D;
// 按方向播放
animancer.Play(_walk4.GetClip(facingDirection));
14.2 Root Motion 重定向
当模型和逻辑在不同 GameObject 时:
| 组件 | 目标类型 | Position | Rotation |
|---|---|---|---|
RedirectRootMotionToTransform |
Transform |
直接赋值 | 直接赋值 |
RedirectRootMotionToRigidbody |
Rigidbody |
MovePosition() |
MoveRotation() |
RedirectRootMotionToCharacterController |
CharacterController |
Move(delta) |
直接赋值 |
基于 OnAnimatorMove() 读取 Animator.deltaPosition/deltaRotation 后转发。
14.3 Sprite 专用功能
| 功能 | 说明 |
|---|---|
SpriteRendererTextureSwap |
运行时替换 Sprite 纹理(换皮) |
DontAllowFade |
禁止 Sprite 动画渐变淡入(像素风) |
14.4 TimeSynchronizer
同步多个 Mixer 子状态的播放进度(如走路/跑步脚步对齐)。
14.5 ExitEvent
简化"等待动画结束后执行"的模式:
var state = animancer.Play(clip);
ExitEvent.Register(state, () => Debug.Log("动画结束"));
14.6 PlayableOutputRefresher
处理 Animator 参数(如 updateMode)在运行时变化时的 PlayableOutput 刷新。
14.7 Animation Jobs
内置 Animation Job 工具:
| 类 | 功能 |
|---|---|
AnimancerJob |
ScriptPlayable 基础 Job |
AnimatedBool |
布尔值动画属性 |
AnimatedInt |
整数动画属性 |
AnimatedFloat |
浮点动画属性 |
AnimatedProperty |
通用属性动画 |
14.8 Clone/Deep Copy 系统
通过 CloneContext 实现深拷贝,管理引用映射避免重复克隆:
// 所有主要类实现 ICopyable<T> / ICloneable<T>
var clonedState = state.Clone(cloneContext);
15. Editor 工具链
15.1 Inspector 调试面板
AnimancerComponent 在运行时提供强大的 Inspector 面板:
- 实时查看所有层、所有状态的权重、时间、速度
- 直接修改运行中的状态属性(时间滑块、速度、权重)
- 播放/暂停单个状态
- 显示 FadeGroup 进度
15.2 Transition 预览
在 Inspector 中选中 ClipTransition 字段时:
- 编辑模式预览动画效果
- 可视化事件时间轴
- 拖拽调整事件位置
15.3 Animancer Tools 窗口
Window → Animation → Animancer Tools
| 工具 | 功能 |
|---|---|
AnimancerSettingsTool |
全局设置 |
GenerateSpriteAnimationsTool |
从 Sprite Sheet 生成 Clip |
PackTexturesTool |
纹理打包 |
ModifySpritesTool |
批量修改 Sprite 属性 |
RenameSpritesTool |
批量重命名 |
RemapAnimationBindingsTool |
重映射动画绑定路径 |
RemapSpriteAnimationTool |
重映射 Sprite 动画 |
AnimationModifierTool |
修改 Clip 属性 |
SpriteDataEditor |
Sprite 数据编辑 |
15.4 TransitionAsset Generator
从 AnimationClip 右键菜单直接生成 TransitionAsset。
15.5 Transition Library Editor (Pro)
可视化编辑 TransitionLibraryAsset:为每对 (from, to) 转换定义 Modifier。
v8.3 编辑器改进:
- Inspector 中
TransitionLibraryAsset字段增加 Edit 按钮,一键打开 Library 编辑窗口 - Fade Duration / Start Time 显示更紧凑清晰
- 支持 Transition 分组:按语义分类(移动/战斗/特殊等),折叠展开大型 Library
- Remove 按钮支持单独移除修正器或整个分组
16. 数据类型与工具
16.1 对象池
| 类 | 功能 |
|---|---|
ObjectPool<T> |
泛型对象池 |
ListPool<T> |
List 池 |
DictionaryPool<K,V> |
Dictionary 池 |
SetPool<T> |
HashSet 池 |
CollectionPool<T> |
ICollection 池 |
StringBuilderPool |
StringBuilder 池 |
16.2 工具类
| 类 | 功能 |
|---|---|
FastEnumerator<T> |
高性能枚举器 |
IndexedList<T> |
带索引的列表 |
Updatable.List |
可更新对象列表 + 调度 |
AnimancerUtilities |
连接/断开 Playable 等扩展方法 |
16.3 接口体系 (16 个)
| 接口 | 用途 |
|---|---|
IAnimancerComponent |
组件契约 |
ITransition / ITransition<T> |
状态创建和配置 |
IState |
FSM 状态 |
IMotion |
Root Motion 数据 |
IUpdatable |
自定义帧更新 |
IHasKey |
键属性 |
IHasEvents |
事件属性 |
IHasDescription |
描述/ToString |
ICloneable<T> / ICopyable<T> |
克隆/深拷贝 |
IConvertable<T> |
类型转换 |
IPolymorphic |
序列化多态 |
IWrapper |
包装对象访问 |
ICharacterRoot |
角色 Root Motion |
IInitializable |
初始化回调 |
IInvokable |
可调用接口 |
IAnimationClipCollection |
动画片段收集 |
17. Animancer vs Unity Mecanim 详细对比
17.1 开发工作流
| 维度 | Mecanim | Animancer |
|---|---|---|
| 播放一个动画 | 创建 Controller → State → Clip → Parameter → Transition → SetTrigger | animancer.Play(clip) |
| 配置文件 | 每角色独立 .controller 资产 | 无需额外资产(可选 TransitionAsset) |
| 状态管理 | Animator Controller 状态图 | C# 代码(可选内置 FSM) |
| 参数传递 | SetFloat/SetBool (魔法字符串) | 直接引用 Clip/Transition |
| 转换条件 | Transition 条件面板 | C# if/else |
| 混合树 | Blend Tree 图形化配置 | MixerState 代码/Inspector |
| 动画层 | Layer 面板 | animancer.Layers[i] |
| 事件 | Animation Events | AnimancerEvent + Action |
| 调试 | 可看状态图但不可改 | 实时修改所有属性 |
17.2 功能矩阵
| 功能 | Mecanim | Animancer Pro |
|---|---|---|
| 播放 Generic/Humanoid/Sprite | ✅ | ✅ |
| Humanoid Retargeting | ✅ | ✅ |
| Humanoid IK | ✅ | ✅ |
| Target Matching | ✅ | ❌ |
| 运行时创建 Clip | ❌ | ✅ |
| 无需 Animator Controller | ❌ | ✅ |
| 无魔法字符串 | ❌ | ✅ |
| 编辑模式动画预览 | ❌ | ✅ |
| 动态 Speed/Time/Weight | 有限 | ✅ 完全 |
| 自定义事件系统 | ❌ | ✅ |
| 自定义 Fade 曲线 | ❌ | ✅ |
| 混合多 Controller | ❌ | ✅ |
| Timeline 混合 | 有限 | ✅ |
| Animation Jobs | ✅ | ✅ |
| FSM | ❌ | ✅ |
| 可视化状态机编辑器 | ✅ | ❌ |
| 源码可访问 | ❌ | ✅ |
17.3 Animancer 十大优势
- 开发效率 — 移除 Animator Controller 中间层
- 代码即文档 — 动画需求在 Inspector 字段中一目了然
- 类型安全 — 编译时检查,无魔法字符串
- 完全可控 — Speed、Time、Weight 任意时刻可读写
- 事件系统 — 基于 Action 委托,精确且灵活
- 可组合性 — 每个脚本独立管理动画
- 调试体验 — 运行时 Inspector 实时可视化和修改
- 渐进式迁移 — HybridAnimancerComponent 可与现有 Controller 共存
- 数据驱动 — Transition 系统将参数从代码中分离
- 源码可用 — 可调试、可修改
17.4 Animancer 劣势
- 无可视化状态机编辑器 — 不适合不写代码的动画师独立工作
- 学习曲线 — 需从 Mecanim 心智模型转换
- 第三方依赖 — 插件维护风险
- Target Matching 缺失 — Humanoid Target Matching 不支持
- 社区规模 — 相比 Mecanim 较小
- Pro 价格 — 核心功能需要 $90
18. 性能分析
18.1 基准测试结果
| 测试项 | 结果 |
|---|---|
| 实例化 | Animancer ≈ Mecanim;按需初始化可快 20-35% |
| 平均帧率 | Animancer 比 Mecanim 快 ~5%(所有 Rig 类型) |
| 内存 | 基本一致(都基于 PlayableGraph) |
18.2 核心优化选项
| 选项 | 说明 |
|---|---|
KeepChildrenConnected = false (默认) |
权重归零时断开 Playable 节点,避免评估不可见动画 |
KeepChildrenConnected = true |
适用于 Sprite 动画(连接/断开开销 > 评估开销) |
| 按需初始化 | 不预创建所有 State,首次播放时才初始化 |
18.3 设计模式带来的性能优势
| 模式 | 说明 |
|---|---|
| 惰性初始化 | Graph、Parameters、Events 均按需创建 |
| 权重断开 | 不可见 Playable 自动断开,GPU 零评估开销 |
| 对象池 | 内置 ObjectPool、ListPool 等减少 GC |
| IUpdatable 调度 | PreUpdate/PostUpdate 列表精确控制更新顺序 |
| 状态注册表 | O(1) 查找已有状态,避免重复创建 |
18.4 限制与注意事项
| 限制 | 说明 |
|---|---|
| AnimatePhysics 模式 | 不能运行时切换 |
| ControllerState 事件 | 对所有 Controller 层触发(非单独) |
| PlayableAssetState | 不支持动态 IK |
| 默认最多 4 层 | 可通过 DefaultCapacity 扩展 |
| IK 仅限 ClipState | Mixer/ParentState 不支持 |
| 循环动画事件 | NormalizedTime 必须 < 1.0 |
19. 与 BaseGames 架构集成方案
19.1 项目定位
根据 BaseGames 架构文档(08_Physics_Animation.md §6):
项目采用 Animancer Pro 作为唯一动画方案,完全替代 Unity Animator Controller。
Animancer 是项目的核心运行时依赖,用于所有角色动画驱动。
19.2 ActorCore 中的引用
public sealed class ActorCore : MonoBehaviour
{
public AnimancerComponent Animancer { get; private set; }
private void Awake()
{
Animancer = GetComponentInChildren<AnimancerComponent>();
}
}
所有子系统通过 ActorCore.Animancer 访问动画。
19.3 AbilityTask 集成 — PlayAnimationTask
PlayAnimationTask 是技能系统中使用最频繁的 Task,直接调用 Animancer API:
[Serializable]
public sealed class PlayAnimationTask : IAbilityTask
{
public TransitionAsset Animation;
public bool WaitForCompletion = true;
private AnimancerState _state;
private bool _ended;
public void Begin(AbilityContext ctx)
{
_ended = false;
_state = ctx.Animancer.Play(Animation);
if (WaitForCompletion)
_state.Events(this).OnEnd ??= () => _ended = true;
}
public bool Tick(AbilityContext ctx, float deltaTime)
=> !WaitForCompletion || _ended;
public void End(AbilityContext ctx) { }
}
关键要点:
- 使用
TransitionAsset(SO) 实现数据驱动,AbilityDefSO 直接引用动画配置 Events(this).OnEnd ??=幂等注册,防止重复绑定WaitForCompletion控制是否阻塞后续 Task
19.4 技能编排示例 — 三段连击
Ability: "三段普攻"
Phase1:
- PlayAnimation: TA_Attack_1_Windup
- ActivateHitbox: { Duration: 0.1 }
- PlayAnimation: TA_Attack_1_Strike
- ApplyDamage: { Tag: Melee, Multiplier: 1.0 }
- PlayAnimation: TA_Attack_1_End
Phase2:
- PlayAnimation: TA_Attack_2_Windup
- ActivateHitbox: { Duration: 0.15 }
- PlayAnimation: TA_Attack_2_Strike
- ApplyDamage: { Tag: Melee, Multiplier: 1.2 }
- PlayAnimation: TA_Attack_2_End
Phase3:
- PlayAnimation: TA_Attack_3_Windup
- ActivateHitbox: { Duration: 0.2 }
- PlayAnimation: TA_Attack_3_Strike
- ApplyDamage: { Tag: Melee, Multiplier: 1.5 }
- PlayAnimation: TA_Attack_3_End
每个 TA_* 都是一个 TransitionAsset,包含 Clip、FadeDuration、Speed、Events。
19.5 Cinematic 系统集成
public sealed class PlayAnimAction : ICinematicAction
{
public TransitionAsset Animation;
public bool WaitForComplete = true;
public bool Execute(CinematicContext ctx)
{
if (_animancer == null)
{
var actor = ctx.CinematicRoot.Find(ActorTag);
_animancer = actor?.GetComponent<AnimancerComponent>();
_state = _animancer.Play(Animation);
if (WaitForComplete)
_state.Events(this).OnEnd ??= () => _ended = true;
}
return !WaitForComplete || _ended;
}
}
19.6 移动混合 — 替代 Blend Tree
[SerializeField] private LinearMixerTransition _moveBlend;
// Inspector 配置: Idle(0) → Walk(0.5) → Run(1.0)
var state = animancer.Play(_moveBlend);
((LinearMixerState)state).Parameter = currentSpeed;
19.7 Transition 层级选择指南
| 场景 | 推荐级别 | 理由 |
|---|---|---|
| 原型开发 / 临时动画 | Level 0 AnimationClip |
最快速 |
| 单脚本专用动画 | Level 1 ClipTransition |
Inspector 可配置 |
| AbilityDefSO 引用 | Level 2 TransitionAsset |
跨技能/跨角色共享 |
| 形态切换时全套动画 | Level 3 TransitionLibrary |
集中管理 + 转换修正器 |
19.8 FSM 集成指南
Animancer 自带 FSM 与 BaseGames 的 GAS-lite 技能系统存在职责划分:
| 场景 | 推荐方案 |
|---|---|
| 技能/Ability 状态管理 | BaseGames GameplayAbilitySystem |
| 角色基础状态 (Idle/Move/Jump/Fall) | Animancer FSM 或自有系统 |
| 纯动画逻辑 (连段内部) | Animancer FSM + InputBuffer |
| AI 行为树 | Behavior Designer |
19.9 迁移路径
Phase 1: 新代码直接使用 Animancer
↓
Phase 2: 已有动画通过 HybridAnimancerComponent 兼容
↓
Phase 3: 逐步将 Animator Controller 逻辑迁移为纯 Animancer
↓
Phase 4: 移除所有 Animator Controller 资产
19.10 架构适配速查表
| 架构组件 | 设计 | 说明 |
|---|---|---|
ActorCore.Animancer |
AnimancerComponent 引用 |
所有系统的动画入口 |
PlayAnimationTask |
TransitionAsset + Events(this).OnEnd |
技能驱动动画 |
PlayAnimAction |
同上 | 过场动画驱动 |
AbilityDefSO |
持有多个 TransitionAsset 字段 |
数据驱动动画配置 |
| 移动混合 | LinearMixerTransition |
替代 Blend Tree |
| 动画事件 | AnimancerEvent.Sequence |
替代 Animation Events |
20. 优缺点总结
20.1 技术评分
| 维度 | 评分 (1-10) | 说明 |
|---|---|---|
| 功能完整度 | 9 | 覆盖 State/Layer/Mixer/Events/FSM/Jobs/Timeline |
| API 设计 | 9 | 极简 Play() 入口 + 丰富的配置层级 |
| 文档质量 | 9 | 官方文档详尽,示例场景 10 组 |
| 性能 | 8 | 与 Mecanim 一致或略优,权重断开优化 |
| 易用性 | 9 | 一行代码上手,Inspector 友好 |
| 可维护性 | 8 | 171 文件、完整源码、Partial 组织清晰 |
| 与项目契合度 | 10 | 架构核心依赖,完全适配 GAS-lite 设计 |
| 综合 | 9.0 | 项目核心动画方案,完全替代 Mecanim |
20.2 核心优势
| 优势 | 说明 |
|---|---|
| 代码驱动 | 与 GAS-lite "代码驱动一切" 理念完全一致 |
| 数据驱动 | TransitionAsset → SO → AbilityDefSO,完美数据管线 |
| 类型安全 | 无魔法字符串,编译时安全 |
| 事件一等公民 | OnEnd 直接解决动画结束通知最大痛点 |
| 调试体验 | 运行时 Inspector 实时可视化 |
| 完整源码 | 可调试可修改可学习 |
| 渐进迁移 | Hybrid 组件平滑过渡 |
| Sprite 优化 | 像素风专用优化 (DontAllowFade, KeepChildrenConnected) |
20.3 风险与缓解
| 风险 | 缓解方案 |
|---|---|
| 第三方依赖 | Pro 版有完整源码,可自行维护 |
| 无 Target Matching | 项目为 2D,不需要此功能 |
| 无可视化编辑器 | 策划通过 TransitionAsset Inspector 配置 |
21. 总结与建议
21.1 总体评价
Animancer Pro v8.3.0 是 Unity 生态中最成熟的代码驱动动画方案。对于 BaseGames 这一 2D Metroidvania 项目:
- 核心动画引擎 — 已作为唯一动画方案深度集成
- 与技能系统无缝配合 — TransitionAsset + PlayAnimationTask 构成完整数据管线
- 性能可靠 — 权重断开/惰性初始化/对象池等优化到位
- Sprite 友好 — DontAllowFade/KeepChildrenConnected/SpriteRendererTextureSwap
- v8.3 增强 — TransitionLibrary 分组/TryGetAlias 别名查找/Event.Sequence.IndexOf/WeightedMaskLayers Root Motion 权重
21.2 最佳实践
| 实践 | 建议 |
|---|---|
| 事件绑定 | 始终使用 Events(this).OnEnd ??= 幂等模式 |
| Transition 选择 | AbilityDefSO 用 TransitionAsset,脚本内用 ClipTransition |
| FadeMode | 连击用 FromStart,通用用 FixedSpeed |
| Sprite 动画 | 设置 KeepChildrenConnected = true 减少连接开销 |
| 性能模式 | 生产版本不影响(Inspector 开销仅编辑器) |
| 层管理 | Layer 0 全身,Layer 1+ 覆盖层(上半身/表情) |
| 参数绑定 | Mixer 使用 ParameterName 自动绑定到 ParameterDictionary |
21.3 关键文件速查
| 用途 | 类名 | 路径 |
|---|---|---|
| 主组件 | AnimancerComponent |
Runtime/AnimancerComponent.cs |
| 核心图 | AnimancerGraph |
Runtime/Core/AnimancerGraph.cs |
| 片段状态 | ClipState |
Runtime/Core/Nodes/ClipState.cs |
| 动画层 | AnimancerLayer |
Runtime/Core/Nodes/AnimancerLayer.cs |
| 事件 | AnimancerEvent |
Runtime/Core/Events/AnimancerEvent.cs |
| 事件序列 | AnimancerEvent.Sequence |
Runtime/Core/Events/AnimancerEvent.Sequence.cs |
| 淡入淡出 | FadeGroup |
Runtime/Core/Fades/FadeGroup.cs |
| Transition 接口 | ITransition |
Runtime/Interfaces/ITransition.cs |
| ClipTransition | ClipTransition |
Runtime/Utilities/Transitions/Transition Types/ClipTransition.cs |
| TransitionAsset | TransitionAsset |
Runtime/Utilities/Transitions/TransitionAsset.cs |
| TransitionLibrary | TransitionLibraryAsset |
Runtime/Utilities/Transitions/Transition Libraries/TransitionLibraryAsset.cs |
| 线性混合 | LinearMixerState |
Runtime/Mixer States/LinearMixerState.cs |
| 方向混合 | DirectionalMixerState |
Runtime/Mixer States/DirectionalMixerState.cs |
| Controller 状态 | ControllerState |
Runtime/Controller States/ControllerState.cs |
| FSM | StateMachine<T> |
Runtime/Utilities/FSM/StateMachine1.cs |
| IState | IState |
Runtime/Utilities/FSM/IState.cs |
| 输入缓冲 | InputBuffer |
Runtime/Utilities/FSM/StateMachine1.InputBuffer.cs |
| 缓动 | Easing |
Runtime/Utilities/Custom Fade/Easing.cs |
| Root Motion | RedirectRootMotion* |
Runtime/Utilities/Redirect Root Motion/ |
| Weighted Mask | WeightedMaskLayers |
Runtime/Core/Weighted Mask Layers/WeightedMaskLayers.cs |
| 参数字典 | ParameterDictionary |
Runtime/Data Types/Parameters/ParameterDictionary.cs |
| 方向动画 | DirectionalAnimationSet* |
Runtime/Utilities/Directional Animations/ |
| 对象池 | ObjectPool<T> |
Runtime/Data Types/Object Pooling/ObjectPool.cs |
文档版本: 1.1
基于: Animancer Pro v8.3.0 源码分析 (171 个源文件) + 官方文档 + BaseGames 架构文档
源文档:Docs/Guides/Animancer_Technical_Evaluation.md
架构参考:Docs/Architecture/08_Physics_Animation.md§6、05_Ability_System.md§5、18_Cinematic_System.md