Files
zeling_v2/Docs/ThirdPart/Animancer_Technical_Evaluation.md
2026-05-19 23:20:44 +08:00

61 KiB
Raw Blame History

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/
命名空间: AnimancerAnimancer.FSMAnimancer.TransitionLibraries


目录

  1. 概述与设计哲学
  2. 架构总览
  3. 核心组件
  4. 节点层级体系 (Nodes)
  5. 状态系统 (States)
  6. Transition 系统
  7. 事件系统 (Events)
  8. Fade 与权重系统
  9. Mixer 状态 (混合树等价)
  10. 动画层 (Layers)
  11. Controller State (Mecanim 兼容)
  12. 内置有限状态机 (FSM)
  13. 参数系统 (Parameters)
  14. 高级特性
  15. Editor 工具链
  16. 数据类型与工具
  17. Animancer vs Unity Mecanim 详细对比
  18. 性能分析
  19. 与 BaseGames 架构集成方案
  20. 优缺点总结
  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<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 权重贡献 (01)
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
    // 支持 ModifierA → 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 十大优势

  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 中的引用

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 项目:

  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<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