在这篇文章中,我们将从零开始学习 UE 的骨骼动画基本使用方法,通过一个 demo 工程,演示如何利用 UE 提供的骨骼动画能力来实现角色在不同速度和方向下的移动效果。
新建 Demo 工程 #
运行 UE,新建一个工程,这里简单使用了「Third Person」模板并命名为 UeAnim。新建完成后,导入模型和动画资源,这里使用了 UE 官方的「Animation Starter Pack」,它可以在 UE 的 marketplace 中找到:
导入后,目录结构如下:
接下来删除 viewport 中的原始角色,并修改 Source/UeAnim/UeAnimGameMode.cpp
中的 DefaultPawnClass
对应的蓝图,我们之后不会用到原始的资源:
AUeAnimGameMode::AUeAnimGameMode() {
static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/AnimStarterPack/Ue4ASP_Character"));
if (PlayerPawnBPClass.Class != NULL) {
DefaultPawnClass = PlayerPawnBPClass.Class;
}
}
编译代码,并将「World Settings」中的「GameMode Override」修改为对应的 game mode,这里是 UeAnimGameMode
:
此时点击「Play」按钮,现了「Animation Starter Pack」里的模型:
资源类型说明 #
打开 Content/AnimStarterPack/UE4_Mannequin/Mesh
目录,可以看到三个资源:
紫红色资源 Skeletal Mesh1 SK_Mannequin
Skeletal Mesh 资源是骨骼动画要控制的目标。网格体 mesh 分为静态网格体 static mesh 和骨骼网格体 skeletal mesh 两种,两者的区别在于 skeletal mesh 可以被动画化,因为它具有和骨骼的绑定关系,通过移动骨骼可以实现对它的变形。这里需要提到一个「蒙皮」概念,蒙皮是指把 mesh 的顶点绑定到骨骼上,并且每个顶点可以被多个骨骼按一定权重进行控制。需要注意的是蒙皮是一个容易让人误解的词,这里的「皮」不是指贴图,而是 mesh 本身。
也就是说,我们看到 skeletal mesh 的动画并不是动画师直接操作 mesh 顶点实现的,而是通过操作骨骼实现的。而骨骼的定义则是通过下面要说的 Skeleton 资源实现。
青色资源 Skeleton2 SK_Mannequin_Skeleton
Skeleton 资源是整个动画系统的基础,它是一组相互连接结构化排布的骨骼,我们可以通过改变骨骼的朝向和位置来生成动画。「骨骼」也是一个容易被误解的词,因为动画师控制的其实不是「骨骼」而是「关节」,「骨骼」是「关节」之间的空位,因此事实上一般提到「骨骼」都是指「关节」。
橘黄色资源 Physis Asset3 SK_Mannequin_PhysicsAsset
Physis Asset 用于定义该模型使用的物理和碰撞信息。
在上两层目录,即 Content/AnimStarterPack
中有许多资源文件,这些都是动画相关的文件,其中:
绿色资源 Animation Sequence4 如 Aim_Space_Hip
Animation Sequence 是可在骨架网格体上播放的单个动画资源,记录骨骼随时间的运动状态信息,也就是定义了动画。需要注意的是,每个 animation sequence 资源专门针对特定的 skeleton,且只能在这个 skeleton 上播放,为了能在多个 skeletal mesh 上共享动画,它们必须要使用同一个 skeleton 资源。
蓝色资Class5 Ue4ASP_Character
Blueprint 是 UE 中的可视化脚本,可以通过拖拽节点的方式构建游戏逻辑。
褐色资源 Animation Blueprint6 UE4ASP_HeroTPP_AnimBlueprint
Animation Blueprint 资源和一般的蓝图类似,也是可视化脚本,可用于创建和控制动画行为。前面的 animation sequence 资源仅定义了动画本身,并不记录何时播放以及如何播放的信息,我们需要通过 animation blueprint 对动画播放进行控制。
橙色资源 Blend Space6 如 BS_CrouchWalk
Blend Space 资源可以根据多个输入的值混合 animation sequence,创建出多个动画间的过渡效果。
动画混合 #
一般来说,UE 本身不用于制作动画,我们仅会去导入并使用动画资源,例如控制一个角色何时播放哪些动画,动画之间如何切换等,或在其上进行微调。模型和动画资源是由美术使用类似 Maya 之类的工具制作的。我们拿到这些动画资源并导入后,可以双击 animation sequence 资源打开 animation editor 查看单个动画的预览效果:
在使用这些动画之前,我们需要先实现在多个动画之间的平滑切换。例如,我们想实现一个角色从静止逐步加速,先变为走路,再加速到跑步的效果,我们不会对这个过程中每一个速度值都设计一个动画,而会设计静止、走路、跑步三个动画,分别对应于角色移动速度为 0、1.5m/s、3m/s 时的状态,这之间的其他速度值就用这几个动画混合生成。我们可以用前面提到的 blend space 来定义这个生成逻辑。Blend space 有两种,一种是普通的 blend space,另一种是 blend space 1D,其中 blend space 的混合参数值有两个,blend space 1D 的混合。这里以 blend space 为例说明,在 Content Browser 中新建一个 blend space 资源:
前面提到,每个骨骼动画都是专门针对特定的 skeleton 实现的,因此 blend space 显然也需要针对特定 skeleton 实现。UE 会在创建 blend space 的时候要求我们指明对应的 skelton 资源,这里选择 AnimStarterPack
目录下的 skeleton:
双击这个这个资源后,我们可以在 Animation Editor 中编辑 blend space:
在 blend space 中,我们可以根据两个参数的值来确定动画的混合逻辑,在 editor 的下方可以看到一个二维的坐标系,两个参数分别对应两个坐标轴,拖动绿点可以在上方查看混合的效果:
这里坐标轴的对应的名字和其变化范围可以在左侧的「Asset Details」中设置,这里将 x 轴设为方向,取值为 -90~90,y 轴设为移动速度,取值为 0~300:
然后,将左侧的 Asset Browser 面板中的动画资源拖动到坐标系中对应的位置,例如当旋转 0 度,速度为 0 的时候是 idle 动画,那么就将 idle 动画拖到 direction 为 0 且 speed 为 0 的位置上:
类似地,我们可以将向左走路动画放在 direction 为 -90 speed 为 150 的位置,向右跑步的动画放在 direction 为 90 speed 为 300 的位置……将这些动画放好后,我们可以拖动绿点进行预览:
动画控制 #
为了使用动画,我们需要动画播放的控制器,前面提到,UE 通过 animation blueprint 控制动画行为。在 Content Browser 中新建一个 animation blueprint 资源,命名为 BP_Anim
,这里同样要指定使用 AnimStarterPack
目录下的 skeleton:
双击打开新建的 blueprint 进入 Animation Blueprint Editor,可以看到中间有两个 tab,一个是 Event Graph 一个是 AnimGraph:
默认情况下,AnimGraph 中只有一个「Output Pose」节点,我们可以将任意动画从右侧的 Asset Browser 面板中拖入 AnimGraph 里,然后将动画的输出连到 Output Pose 节点的输入上:
此时点击「Compile」按钮,会发现动画节点和 Output Pose 节点之间的连线亮起,在预览面板中可以看到动画播放的效果:
但这样的连接并不能实现状态的转换,例如在点击蹲下后将角色动画切到蹲下的动画。在 animation blueprint 中,我们通过状态机来实现这样的转换功能。删除刚刚添加的动画节点,然后右键添加一个 State Machine 节点,并将其输出连接到 Output Pose 的输入上:
双击新增的 State Machine 节点,进入该节点的编辑界面,如果需要返回刚刚的 AnimGraph 界面,可以点击顶部的「AnimGraph」。默认情况下,这里只有一个「Entry」节点,我们拖动这个节点的输出,可以新增节点,这里新增一个 State 节点:
将这个 state 节点命名为 Normal,这个节点用于表示通常状态下的动画。双击这个节点,进入这个 Normal 节点的编辑界面,我们可以看到和之前 Output Pose 类似的一个动画输出节点 Output Animation Pose。此时我们可以从左侧的 Asset Browser 面板中拖出之前的 blend space 资源,并将其输出连接到 Output Animation Pose 的输入上:
问题是我们的 blend space 需要当前的方向和速度作为输入,这个数据又要从哪来呢?我们可以点击上方的 Event Graph tab,切换到事件编辑界面:
在右下方的 My Blueprint 面板中找到「Variable」session,添加两个 float
类型的变量,命名为 Speed
和 Direction
用于表示速度和方向:
接下来,我们需要设置这两个变量,首先,新建一个 Get Player Character 节点,并将其类型转换到我们使用的 character 类型上,这里是 Ue4ASP_Character
。从这个节点出发,获取其 Velocity 并计算其长度,这个就是角色当前的速度值,将这个值设给 Speed
变量。然后,通过 Calculate Direction 节点获取当前方向,并赋值给 Direction
变量,大致如下图所示:
此时我们可以回到 Normal 节点的编辑界面,将 Speed
和 Direction
两个变量赋值给 blend space 的对应位置。编译后,我们可以在左侧「Anim Preview」面板中输入不同的速度和方向值,就可以在左侧的预览面板中看到具体效果:
目前我们的状态机只有一个状态,我们可以添加更多状态并定义状态之间的转换规则。回到之前的 state machine 编辑界面,从 Normal 节点出发再拖一个节点出来,命名为 Crouch,这个节点用于表示下蹲状态下的动画。此时我们发现 Normal 和 Crouch 之间有一个绘制了双向箭头的圆圈,这个是用于表示两个状态之间的转换规则。由于我们之前是从 Normal 节点出发添加的 Crouch 节点,因此 UE 自动建立了 Normal 到 Crouch 的转换,为了将状态转回去,这里从 Crouch 节点出发,将箭头指向 Normal 节点:
为了标记角色是否是蹲下状态,我们添加一个 bool
变量,命名为 Crouched
并从 character blueprint 中获取 IsCrouched
的值,并赋值给它:
如果我们需要用该蓝图没有提供的状态,那么就需要去该 character 蓝图中自行添加,然后再在此处获取。
回到 state machine 编辑界面,双击从 Normal 到 Crouch 的转换规则圆圈,进入转换规则编辑界面,将 Crouched
变量的值赋给 Result 节点:
类似地,在 Crouch 到 Normal 的转换规则中,将 not Crouched
的值赋给 Result 节点:
而在 Crouch 状态中,我们也给 Output Animation Pose 输入一个动画,这里就不重复 blend space 的制作了,简单将一个 idle 的蹲下动画作为输入:
此时可以修改 Anim Preview 面板中的数值来预览动画状态改变的效果了:
应用动画 #
在制作好前面的动画后,我们可以打开 Ue4ASP_Character
蓝图,在 Viewport 面板中选中我们的角色模型,然后在右侧的 Details 面板中找到 Animation 一节,将其中的「Animation Mode」改为「Use Animation Blueprint」,再将「Anim Class」改为刚刚制作的动画 BP_Anim
:
另外,为了实现蹲下的能力,我们还需要做几处修改。首先在 Ue4ASP_Character
蓝图中间的 Event Graph 中找到 Crouching 组,在这里修改蓝图逻辑来触发角色的蹲下状态。简单起见,这里不作复杂判断,直接在 Crouch Button Down 为 true
的时候触发蹲下, false
的时候解除蹲下:
然后,我们在左侧的 Components 面板中选中 Character Movement 一项,在右侧的 Details 面板中找到 Nav Movement 一节,勾选其中的「Can Crouch」,确保可以蹲下:
修改好后保存更改并编译。最后,在菜单栏的 Edit 菜单下点击「Project Settings…」,然后在 Input 菜单中的 Action Mappings 列表里加一项「Crouch」,并绑定一个按键,这里绑定的是左 Ctrl 键:
回到主界面,点击「Play」运行游戏,就可以用 WASD 键控制方向,用左 Ctrl 蹲下,查看动画效果了:
- 骨架网格体 | 虚幻引擎文档 ↩︎
- 骨架资源 | 虚幻引擎文档 ↩︎
- 物理资产编辑器 | 虚幻引擎文档 ↩︎
- 动画序列 | 虚幻引擎文档 ↩︎
- 动画蓝图 | 虚幻引擎文档 ↩︎
- 混合空间 | 虚幻引擎文档 ↩︎ ↩︎