# 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` --- ## 目录 1. [概述与设计哲学](#1-概述与设计哲学) 2. [架构总览](#2-架构总览) 3. [核心组件](#3-核心组件) 4. [节点层级体系 (Nodes)](#4-节点层级体系-nodes) 5. [状态系统 (States)](#5-状态系统-states) 6. [Transition 系统](#6-transition-系统) 7. [事件系统 (Events)](#7-事件系统-events) 8. [Fade 与权重系统](#8-fade-与权重系统) 9. [Mixer 状态 (混合树等价)](#9-mixer-状态-混合树等价) 10. [动画层 (Layers)](#10-动画层-layers) 11. [Controller State (Mecanim 兼容)](#11-controller-state-mecanim-兼容) 12. [内置有限状态机 (FSM)](#12-内置有限状态机-fsm) 13. [参数系统 (Parameters)](#13-参数系统-parameters) 14. [高级特性](#14-高级特性) 15. [Editor 工具链](#15-editor-工具链) 16. [数据类型与工具](#16-数据类型与工具) 17. [Animancer vs Unity Mecanim 详细对比](#17-animancer-vs-unity-mecanim-详细对比) 18. [性能分析](#18-性能分析) 19. [与 BaseGames 架构集成方案](#19-与-basegames-架构集成方案) 20. [优缺点总结](#20-优缺点总结) 21. [总结与建议](#21-总结与建议) --- ## 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 — 自定义 Animation Job ├── SequenceState — 序列播放 └── ParentState (抽象容器) ├── ManualMixerState — 手动权重混合 └── MixerState — 参数化混合 ├── 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, 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.cs │ │ ├── ListPool / DictionaryPool / SetPool / CollectionPool │ │ └── StringBuilderPool │ ├── Interfaces/ (16 文件) │ │ IAnimancerComponent, ITransition, IState, IMotion, │ │ IUpdatable, IHasKey, IHasEvents, IHasDescription, │ │ ICloneable, ICopyable, IConvertable, │ │ 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 上。 ```csharp [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 通过字符串名称注册和查找动画: ```csharp 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 的最小配置: ```csharp 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: ```csharp 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: ```csharp public sealed class ClipState : AnimancerState { public AnimationClip Clip { get; } // 内部创建 AnimationClipPlayable // 支持所有 Rig 类型:Humanoid, Generic, Sprite } ``` ### 5.3 PlayableAssetState (Pro) 包装 `PlayableAsset` (Timeline) 作为 Animancer 图中的一个节点,可与其他状态混合: ```csharp animancer.Play(myTimelineTransition); // Timeline 作为普通 AnimancerState 参与权重混合 ``` ### 5.4 SequenceState (Pro) 按顺序播放一系列子状态,支持子状态间淡入时间: ```csharp public class SequenceState : ParentState, IUpdatable { void Set(params ITransition[] transitions); float Length { get; } // 所有子动画总长度 } ``` ### 5.5 AnimationJobState (Pro) 运行自定义 `IAnimationJob`,实现程序化动画: ```csharp 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 : AnimancerState, IUpdatable where T : struct, IAnimancerStateJob { public T Job { get; set; } } ``` ### 5.6 AnimancerStateDictionary 状态注册表,映射键到状态: ```csharp 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 接口 ```csharp 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 类型: ```csharp [Serializable] public class ClipTransition : Transition, IMotion, IAnimationClipCollection { [SerializeField] private AnimationClip _Clip; [SerializeField] private float _NormalizedStartTime; // 继承自 Transition: // 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) ```csharp [CreateAssetMenu(menuName = "Animancer/Transition Asset")] public class TransitionAsset : TransitionAsset { // 可在 Project 窗口右键创建 // 多角色共享同一配置 // 注意:Events 不应存储在共享 Asset 上 // 正确做法:state.Events(this).OnEnd ??= callback } ``` ### 6.5 TransitionLibraryAsset (Pro) ```csharp [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 结构 ```csharp public partial struct AnimancerEvent { public float normalizedTime; // 触发时间 [0,1] public Action callback; // 回调委托 // 特殊常量 public const float AlmostOne = 0.99999994f; // 循环动画末尾事件 // 参数化事件 public static void Parametize(Action callback); public static T GetCurrentParameter(); } ``` ### 7.2 AnimancerEvent.Sequence ```csharp public class Sequence : IEnumerable { 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 的本地事件副本。 ```csharp // ✅ 推荐写法:幂等事件绑定 AnimancerState state = _Animancer.Play(_Action); state.Events(this).OnEnd ??= OnActionEnd; // ??= 保证只赋值一次 // ❌ 错误写法:每次重新赋值导致 GC state.Events(this).OnEnd = OnActionEnd; // 每次新建 delegate ``` `this` 参数的作用: - 将事件绑定到该组件的生命周期 - 组件销毁时自动清理事件 - 同一 State 可被不同组件绑定不同事件 ### 7.4 命名事件系统 ```csharp 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` | 类型安全的参数化事件 | | `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 管理状态间权重淡入淡出的核心类。 ```csharp public class FadeGroup { float FadeSpeed { get; set; } float RemainingFadeTime { get; } // 自定义缓动 void SetEasing(Func easing); void SetEasing(Easing.Function function); } ``` ### 8.2 自定义 Fade 缓动 ```csharp 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 动画淡入淡出(像素风不适合渐变): ```csharp [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 (手动混合) ```csharp 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 (参数化混合基类) ```csharp public abstract class MixerState : ManualMixerState { T Parameter { get; set; } // 驱动参数 T NormalizedParameter { get; set; } // 归一化参数 T[] Thresholds { get; } // 阈值数组 // 子类实现 abstract void CalculateWeights(); // 混合权重算法 // 参数绑定 StringReference ParameterName { get; set; } // 绑定到 ParameterDictionary } ``` ### 9.4 LinearMixerState (1D 混合) ```csharp public class LinearMixerState : MixerState { float MinThreshold { get; } float MaxThreshold { get; } bool ExtrapolateSpeed { get; set; } // 参数超阈值时自动加速 void Add(AnimancerState state, float threshold); void AssertThresholdsSorted(); } ``` **用法示例**: ```csharp [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 混合) ```csharp public abstract class Vector2MixerState : MixerState { 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`: ```csharp 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 ```csharp public sealed class AnimancerLayer : AnimancerNode { // ─── 状态管理 ─── AnimancerState CurrentState { get; } IReadOnlyList 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 ```csharp public abstract class AnimancerLayerList : IEnumerable { 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 支持**每骨骼浮点权重**: ```csharp [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` 逐骨骼混合权重。 **v8.3 新增 — Root Motion 权重**:每层可独立设置 Root Motion 影响权重,`WeightedMaskLayersDefinition` 新增 `RootMotionWeights` 数组,`WeightedMaskMixerJob` 通过 `NativeArray rootMotionWeights` 逐层混合 Root Motion 输出。适用于上半身覆盖层不影响角色位移的场景。 ### 10.4 层使用示例 ```csharp // 基础层(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 图中的一个节点: ```csharp 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 接口 ```csharp public interface IState { bool CanEnterState { get; } // 进入守卫 bool CanExitState { get; } // 退出守卫 void OnEnterState(); // 进入回调 void OnExitState(); // 退出回调 } // 扩展接口 — 状态知道自己属于哪个状态机 public interface IOwnedState : IState { StateMachine OwnerStateMachine { get; } } ``` ### 12.2 StateMachine\ (无键状态机) ```csharp public class StateMachine 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\ (带键状态机) ```csharp public class StateMachine : StateMachine 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()` 映射状态进出: ```csharp public abstract class StateBehaviour : MonoBehaviour, IOwnedState { // OnEnable() → 进入状态(Enable 组件) // OnDisable() → 退出状态(Disable 组件) public virtual bool CanEnterState => true; public virtual bool CanExitState => true; } ``` ### 12.5 DelegateState Lambda 快速创建状态: ```csharp var state = new DelegateState( canEnter: () => true, onEnter: () => Debug.Log("Enter"), onExit: () => Debug.Log("Exit") ); ``` ### 12.6 InputBuffer 解决"动作不可中断时输入会丢失"的问题: ```csharp public class InputBuffer { void Buffer(TState state, float timeout); // 缓冲一个输入 void Update(); // 每帧检查能否执行 // 在 timeout 内反复 TrySetState,成功则消耗缓冲 } ``` ### 12.7 StateChange / KeyChange 转换上下文结构,在切换过程中提供 `PreviousState`/`NextState` 信息: ```csharp using (new StateChange(machine, previousState, nextState)) { previousState.OnExitState(); nextState.OnEnterState(); } ``` ### 12.8 FSM 使用架构 ``` Character (MonoBehaviour, hub) ├── AnimancerComponent — 动画 ├── StateMachine.WithDefault — 状态机 └── Equipment / HealthPool — 数据 CharacterState (StateBehaviour, 基类) ├── IdleState — 默认状态 ├── MoveState — 移动 ├── ActionState — 攻击/技能 └── ... Brain (MonoBehaviour, 输入驱动) ├── PlayerBrain — 玩家输入 └── AIBrain — AI 行为 ``` --- ## 13. 参数系统 (Parameters) ### 13.1 ParameterDictionary 全局命名参数字典,供 Mixer 自动绑定: ```csharp // 写入 animancer.Parameters.Set("Speed", 5f); // 读取 float speed = animancer.Parameters.Get("Speed").Value; // 尝试读取 if (animancer.Parameters.TryGet("Speed", out var param)) Debug.Log(param.Value); ``` ### 13.2 Parameter\ 泛型参数,支持变更事件: ```csharp public class Parameter { T Value { get; set; } StringReference Key { get; } Type ValueType { get; } event Action OnValueChanged; } ``` ### 13.3 SmoothedFloatParameter / SmoothedVector2Parameter 平滑参数,自动插值到目标值: ```csharp 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 方向动画集: ```csharp // 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 简化"等待动画结束后执行"的模式: ```csharp 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` 实现深拷贝,管理引用映射避免重复克隆: ```csharp // 所有主要类实现 ICopyable / ICloneable 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` | 泛型对象池 | | `ListPool` | List 池 | | `DictionaryPool` | Dictionary 池 | | `SetPool` | HashSet 池 | | `CollectionPool` | ICollection 池 | | `StringBuilderPool` | StringBuilder 池 | ### 16.2 工具类 | 类 | 功能 | |----|------| | `FastEnumerator` | 高性能枚举器 | | `IndexedList` | 带索引的列表 | | `Updatable.List` | 可更新对象列表 + 调度 | | `AnimancerUtilities` | 连接/断开 Playable 等扩展方法 | ### 16.3 接口体系 (16 个) | 接口 | 用途 | |------|------| | `IAnimancerComponent` | 组件契约 | | `ITransition` / `ITransition` | 状态创建和配置 | | `IState` | FSM 状态 | | `IMotion` | Root Motion 数据 | | `IUpdatable` | 自定义帧更新 | | `IHasKey` | 键属性 | | `IHasEvents` | 事件属性 | | `IHasDescription` | 描述/ToString | | `ICloneable` / `ICopyable` | 克隆/深拷贝 | | `IConvertable` | 类型转换 | | `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 十大优势 1. **开发效率** — 移除 Animator Controller 中间层 2. **代码即文档** — 动画需求在 Inspector 字段中一目了然 3. **类型安全** — 编译时检查,无魔法字符串 4. **完全可控** — Speed、Time、Weight 任意时刻可读写 5. **事件系统** — 基于 Action 委托,精确且灵活 6. **可组合性** — 每个脚本独立管理动画 7. **调试体验** — 运行时 Inspector 实时可视化和修改 8. **渐进式迁移** — HybridAnimancerComponent 可与现有 Controller 共存 9. **数据驱动** — Transition 系统将参数从代码中分离 10. **源码可用** — 可调试、可修改 ### 17.4 Animancer 劣势 1. **无可视化状态机编辑器** — 不适合不写代码的动画师独立工作 2. **学习曲线** — 需从 Mecanim 心智模型转换 3. **第三方依赖** — 插件维护风险 4. **Target Matching 缺失** — Humanoid Target Matching 不支持 5. **社区规模** — 相比 Mecanim 较小 6. **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 中的引用 ```csharp public sealed class ActorCore : MonoBehaviour { public AnimancerComponent Animancer { get; private set; } private void Awake() { Animancer = GetComponentInChildren(); } } ``` 所有子系统通过 `ActorCore.Animancer` 访问动画。 ### 19.3 AbilityTask 集成 — PlayAnimationTask `PlayAnimationTask` 是技能系统中使用最频繁的 Task,直接调用 Animancer API: ```csharp [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 技能编排示例 — 三段连击 ```yaml 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 系统集成 ```csharp 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(); _state = _animancer.Play(Animation); if (WaitForComplete) _state.Events(this).OnEnd ??= () => _ended = true; } return !WaitForComplete || _ended; } } ``` ### 19.6 移动混合 — 替代 Blend Tree ```csharp [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 项目: 1. **核心动画引擎** — 已作为唯一动画方案深度集成 2. **与技能系统无缝配合** — TransitionAsset + PlayAnimationTask 构成完整数据管线 3. **性能可靠** — 权重断开/惰性初始化/对象池等优化到位 4. **Sprite 友好** — DontAllowFade/KeepChildrenConnected/SpriteRendererTextureSwap 5. **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` | `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` | `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`