跳转至

Week5 — 骨骼动画

主要介绍骨骼动画

骨骼动画

资产类型

  • Skeletal Mesh: 骨骼网格
  • Skeleton: 骨骼
  • Physics Asset: 物理资产

一般Root的位置在人物的两脚之间。

动画蓝图

Animation Blueprint(动画蓝图) 是 UE 中控制骨骼动画的核心资产,它包含两个关键图表:

  • Anim Graph: 动画图,用于逐帧生成动画姿势(Pose)
  • Event Graph: 事件图,用于处理动画事件和更新变量
C++
// C++ 中播放动画
if (USkeletalMeshComponent* Mesh = GetMesh())
{
    Mesh->PlayAnimation(JumpAnim, false);  // bLooping = false
    // 或者通过 AnimInstance
    if (UAnimInstance* AnimInst = Mesh->GetAnimInstance())
    {
        AnimInst->Montage_Play(AttackMontage, 1.0f);
    }
}

动画资产

  • Animation Sequence: 动画序列,由一系列关键帧组成,当动画执行到某一关键帧时,会根据关键帧的信息进行插值计算,生成动画效果
  • Animation Additive: 叠加动画,用于叠加在基础动画上的动画
  • Local Space: 本地空间,相对于父骨骼的位置
  • Mesh Space: 网格空间,相对于骨骼模型组建的位置
  • Blend Space: 混合空间,用于混合不同的动画
  • Aim Offset: 瞄准偏移,用于瞄准动画
  • Montage: 动画剪辑,用于播放一段动画,可以由多个动画序列组成,通过设置Section、Slot来控制动画的播放、动画的混合,可以实现一些循环和切换的效果;在属性页设置淡入淡出时间,可以实现动画的平滑切换

状态机(State Machine)

状态机 是动画蓝图中最常用的动画切换控制方式。每个状态(State)对应一个动画或动画混合,状态之间通过 转换规则(Transition Rule) 连接。

Text Only
1
2
3
4
[Idle] --速度 > 10--> [Walk/Run]
[Walk/Run] --速度 < 10--> [Idle]
[Walk/Run] --IsJumping--> [Jump]
[Jump] --IsFalling == false--> [Idle]

状态机设计要点

  • 每个状态内部可以嵌套子状态机,实现更细粒度的控制
  • 转换规则是一个布尔表达式,为 true 时触发切换
  • Conduit 节点用于无动画的纯逻辑判断跳转
  • 注意设置合理的 Blend Time(过渡时间),避免动画突变

混合空间(Blend Space)

Blend Space 根据一个或两个输入参数(如速度、方向)在多个动画之间进行平滑混合。

只有一个输入轴,典型用例: - 输入:Speed(0 ~ 600) - 关键点:Idle(0)→ Walk(150)→ Run(600) - 引擎根据当前 Speed 值自动在相邻动画间插值

有两个输入轴,典型用例: - X 轴:Direction(-180 ~ 180) - Y 轴:Speed(0 ~ 600) - 在网格关键点上放置对应的移动动画(前、后、左、右及其组合)

Aim Offset

Aim Offset 本质是一个 Additive 的 2D Blend Space,输入为 Pitch 和 Yaw,用于根据视角方向叠加瞄准姿势。

动画节点

动画混合节点:

  • ApplyAdditive: 叠加动画
  • ApplyMeshSpaceAdditive: 叠加网格空间动画,在Mesh Space中叠加动画
  • BlendPose: 混合姿势,用于混合不同的动画

空间转换会把输入的Pose中的骨骼位置转换到目标空间中,资源消耗较大,不建议使用。

状态机:图形化地控制动画的播放。

IK:逆向动力学,用于控制骨骼的位置。

动画通知(Animation Notify)

Anim Notify 允许在动画序列的特定帧触发事件,常用于:

  • 脚步声(Footstep)
  • 攻击判定开关(Enable/Disable Hit Detection)
  • 特效生成(Particle Spawn)
  • 粒子/音效触发
C++
// C++ 自定义 Notify
UCLASS()
class UAnimNotify_MeleeHit : public UAnimNotify
{
    GENERATED_BODY()
public:
    virtual void Notify(USkeletalMeshComponent* MeshComp,
                        UAnimSequenceBase* Animation,
                        const FAnimNotifyEventReference& EventRef) override
    {
        if (AActor* Owner = MeshComp->GetOwner())
        {
            // 启用碰撞检测
            // ...
        }
    }
};

动画蒙太奇(Montage)进阶

Montage 支持 Section 划分,可以实现复杂的动画编排:

  • Section:将一个 Montage 分为多段,每段可以独立播放
  • Slot:指定 Montage 在 Anim Graph 中的混合插槽(如 DefaultSlotUpperBody
  • 连击系统:通过 Montage_SetNextSection 动态切换下一段 Section,实现连招
C++
1
2
3
// 蓝图中播放 Montage 并监听结束事件
float Duration = PlayAnimMontage(AttackMontage, 1.0f, FName("Attack1"));
// Montage 结束时会触发 OnMontageEnded 委托

Montage 与 Anim Graph 的关系

Montage 是在 Anim Graph 之外独立播放的,通过 Slot 节点 将 Montage 的结果混合进 Anim Graph 的输出。如果 Anim Graph 中没有对应的 Slot 节点,Montage 将不会显示。