Skip to content

3. Sprite 动画

更新: 4/8/2026 字数: 0 字 时长: 0 分钟

简单播放

整体代码结构与之前的示例非常相似,但不再直接引用单个AnimationClip,而是改用 Directional Animation Sets,一种 so 资产。

Deriectional Aninmation Set 用于为一个行为定义不同方向的动画,例如为 walk 定义四向移动动画。

Example

cs
[SerializeField]
private AnimancerComponent _Animancer;

[SerializeField]
private DirectionalSet<AnimationClip> _Idles;

[SerializeField]
private DirectionalSet<AnimationClip> _Walks;

[SerializeField]
private Vector2 _Facing = Vector2.down;

根据Facing播放动画:

cs
private void Play(DirectionalSet<AnimationClip> animations)
{
    AnimationClip clip = animations.Get(_Facing);
    _Animancer.Play(clip);
}

在编辑模式下预览

在编辑模式下,如果我们创建另一个使用不同动画集的角色,它在运行时会正常使用那些动画,但在编辑模式下不会自动显示正确的精灵,除非手动重新赋值。

我们可以让角色采样自身动画的第零帧来解决这个问题。只需要在MonoBehaviour.OnValidate()当中调用AnimancerUtilities.EditModeSampleAnimation()即可:

cs
#if UNITY_EDITOR
private void OnValidate()
{
    // EditModeSampleAnimation 会自动处理 AnimationClip 和 _Animancer 的空检查
    if (_Idles != null)
    {
        _Idles.Get(_Facing).EditModeSampleAnimation(_Animancer);
        // .EditModePlay() 会完成播完动画
    }
}
#endif

将输入投影到可可移动的方向上

使用Snap方法将输入向量限制到动画集所支持的最接近的方向,这样你就可以支持任意数量的方向,而不需要将代码硬编码为特定方向数量。

cs
_Movement = _CurrentAnimationSet.Snap(_Movement);

动画同步

不加额外处理的话,通常每次在 Walk 和 Run 之间切换时,动画都会从头开始播放。平滑动画中,角色可能会突然从 Walk 周期的某一部分跳到 Run 周期的完全不同部分,看起来非常突兀。

这个问题可以通过TimeSynchronizer来解决。它可以在切换动画时同步相关动画的 NormalizedTime,让新动画从对应的进度继续播放,从而实现自然的过渡。

我们首先定义一个简单的enum,用于对动画进行分组:

cs
private enum AnimationGroup
{
    Other,      // Idle 和其他不相关动画
    Movement,   // Walk、Run、Push(这些动画需要保持时间同步)
}

然后创建一个TimeSynchronizer来管理同步:

cs
#private TimeSynchronizer<AnimationGroup> _TimeSynchronizer;

在 Awake 中初始化:

cs
protected virtual void Awake()
{
    _CurrentAnimationSet = _Idle;
    _TimeSynchronizer = new TimeSynchronizer<AnimationGroup>();
}

更新 Play 方法,让它接收一个AnimationGroup参数,并在播放动画前后进行时间存储和同步:

cs
private void Play(DirectionalSet<AnimationClip> animations, AnimationGroup group)
{
    _TimeSynchronizer.StoreTime(_Animancer);  // 先保存当前动画的时间
    _CurrentAnimationSet = animations;
    _Animancer.Play(animations.Get(_Facing));  // 播放新动画
    _TimeSynchronizer.SyncTime(_Animancer, group);  // 同步到新动画
}

3d 世界中的不同

与 2d 角色基本的处理无太大区别,具体调整有:

  • 角色始终面向摄像机。
  • 如若摄像机可旋转,角色不同方向的动画也需随之改变。