1786 lines
61 KiB
Markdown
1786 lines
61 KiB
Markdown
# 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<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 上。
|
||
|
||
```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<T> (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<T> : 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<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)
|
||
|
||
```csharp
|
||
[CreateAssetMenu(menuName = "Animancer/Transition Asset")]
|
||
public class TransitionAsset : TransitionAsset<ITransition>
|
||
{
|
||
// 可在 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<T>(Action<T> callback);
|
||
public static T GetCurrentParameter<T>();
|
||
}
|
||
```
|
||
|
||
### 7.2 AnimancerEvent.Sequence
|
||
|
||
```csharp
|
||
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 的本地事件副本。
|
||
|
||
```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<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
|
||
|
||
管理状态间权重淡入淡出的核心类。
|
||
|
||
```csharp
|
||
public class FadeGroup
|
||
{
|
||
float FadeSpeed { get; set; }
|
||
float RemainingFadeTime { get; }
|
||
|
||
// 自定义缓动
|
||
void SetEasing(Func<float, float> 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<T> (参数化混合基类)
|
||
|
||
```csharp
|
||
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 混合)
|
||
|
||
```csharp
|
||
public class LinearMixerState : MixerState<float>
|
||
{
|
||
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<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`:
|
||
|
||
```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<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
|
||
|
||
```csharp
|
||
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 支持**每骨骼浮点权重**:
|
||
|
||
```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<float>` 逐骨骼混合权重。
|
||
|
||
**v8.3 新增 — Root Motion 权重**:每层可独立设置 Root Motion 影响权重,`WeightedMaskLayersDefinition` 新增 `RootMotionWeights` 数组,`WeightedMaskMixerJob` 通过 `NativeArray<float> 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<TState> : IState
|
||
{
|
||
StateMachine<TState> OwnerStateMachine { get; }
|
||
}
|
||
```
|
||
|
||
### 12.2 StateMachine\<TState\> (无键状态机)
|
||
|
||
```csharp
|
||
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\> (带键状态机)
|
||
|
||
```csharp
|
||
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()` 映射状态进出:
|
||
|
||
```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<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 自动绑定:
|
||
|
||
```csharp
|
||
// 写入
|
||
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\>
|
||
|
||
泛型参数,支持变更事件:
|
||
|
||
```csharp
|
||
public class Parameter<T>
|
||
{
|
||
T Value { get; set; }
|
||
StringReference Key { get; }
|
||
Type ValueType { get; }
|
||
event Action<T> 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<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 中的引用
|
||
|
||
```csharp
|
||
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:
|
||
|
||
```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<AnimancerComponent>();
|
||
_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<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`
|