本课程使用的免费资源:
帕拉贡幽灵
https://www.fab.com/listings/17e0840f-8651-4933-bd6d-211a34b1dd17
教学前览:
有这么一个需求: 使用各种动画资产, 构建一个角色的动画蓝图, 在这个蓝图中,我们需要组织调用角色的前, 后, 左, 右, 移动, 跳跃, 各种基本动画资产, 然后实现的效果: 角色挂载这个动画蓝图后, 可以实现角色的前, 后, 左, 右, 移动, 跳跃;
我们需要:
- 理解:什么是动画资产,什么是动画蓝图, 动画蓝图为什么可以组织调度动画资产...
- 掌握蓝图的基础用法和动画资源的基本特性
- 从0开始搭建一个混合空间用来高效调度动画资产
- 用状态机根据角色的各种状态切换不同的动作
一. 虚幻引擎中角色动效的核心组件:
Skeleton(骨骼) 相当于人体的骨架:是一套 "关节结构标准",规定了角色有哪些关节(比如肩、肘、膝盖)、关节怎么连接。它是后续所有动画、模型绑定的 "基础模板"。
Skeleton Mesh(骨骼网格体) 相当于人体的皮肤 + 肌肉:是角色的可视化模型(比如人物的身体、衣服)。它必须 "绑定" 到 Skeleton 上(这个过程叫 "蒙皮"),这样骨骼动的时候,Mesh 才会跟着变形(比如胳膊肘弯,手臂模型也会弯)。
Animation(动画) 相当于人体的动作数据:比如 "走路""跑步""跳跃" 这些具体动作,是基于 Skeleton 的关节做的(比如让膝盖关节弯曲来做抬腿动作)。所以 Animation 必须和 Skeleton 的关节结构对应,否则没法用在对应的角色上。
Animation Blueprint(动画蓝图) 相当于控制动作的 "大脑":是用来管理 Animation 的逻辑容器。比如判断 "角色移动速度快就播跑步动画、速度慢就播走路动画",还能实现动画混合(比如边走路边挥手)。它会调用前面的 Animation,最终让绑定在 Skeleton 上的 Mesh "动起来"。
动画蓝图 (ABP) > 状态机 (State Machine) > 混合空间 (Blend Space)
二. 它们的依赖关系(流程)
Skeleton(核心基础)→ 绑定Mesh(可视化模型)``Skeleton→ 制作Animation(动作数据)``Animation→ 被Animation Blueprint(逻辑控制器)调用最终:
Animation Blueprint驱动Skeleton,带动Mesh呈现出动态效果
注意: Animation Blueprint驱动``Skeleton的逻辑由其自身完成, 但是如何调用这些逻辑去驱动动画,是由C++程序完成的
三. 动画蓝图
1. 创建并使用动画蓝图:
创建动画蓝图:
新建一个Animation文件夹, 存放动画蓝图, 创建一个动画蓝图;
选择幽灵骨骼,命名为ABP_ShooterCharacter
在角色中调用动画蓝图:
进入你需要管理的角色蓝图中, 修改其动画模式, 选择使用动画蓝图, 然后选择我们的动画类: ABP_ShooterCharacter
2. 动画蓝图的基本操作:
加入资源
这是最终输出点, 右下角的资产浏览器里面搜索你需要的动画资源, 可以拖入场景中
删除节点之间的线:
按住Alt键点任意一端的小人就可以了
删除节点:
单独删除: 直接左键点击, 然后按Del
删除一堆: 左键长按滑动, 可以选中一堆
设置循环动画:
设置双路混合节点:
右击空白处, 搜索Two Way Blend
Alpha变量用于控制混合程度, 为0时仅播放A动画, 为1时仅播B, 0.5时等比例播放
添加变量:
Alpha值可以创建一个变量单独控制, 这样每次更改无需重新编译;
坐下角窗口面板添加变量命名为Speed
然后拖到场景中创建:
编译后在右下角调节Speed
四. 混合空间
在移动系统中: 你不仅需要"走"和"跑"两个状态,你还需要"左走"、"右走"、"左前跑"、"右后跑"等几十个状态。这些状态之间的连线(Transition)会变得像蜘蛛网一样极其复杂,难以维护。
所以我们使用混合空间, 它能让我们用二维的方式管理动画单元, 移动空间是组织调度管理蓝图资产的高效手段;
创建混合空间:
选好骨骼类型后,命名为: BS_Locomation (举例,命名随你)
混合空间使用方式:
在Axis Setting里面定义坐标名, 然后设置取值范围, 然后在坐标轴上, 横轴角度代表角色朝向, 竖轴速度代表角色移速, 任何一个点,都对应着一个玩家二维状态信息, 都可以为此状态玩家设置一个动画单元, 例如: 在速度为0时, 应该为角色添加待机状态, 搜索资源然后拖出来, 按Shift吸附到网格上;两个节点之间按Ctrl可以实时预览
节点之间的连线是引擎自动生成的 "混合权重计算路径"------ 当你的角色参数(比如 Speed 从 0 涨到 100)落在这条连线上 / 附近时,引擎会根据参数到两个采样点的距离,自动分配这两个动画的 "混合权重":
- 比如参数接近底部点(Speed≈0):"站立动画" 的权重占比高,"走路动画" 占比低;
- 参数接近橙色点(Speed≈100):"走路动画" 占比高,"站立动画" 占比低;
- 参数在连线中间(比如 Speed=50):两个动画各占一部分权重,最终呈现的是 "站立→走路" 的过渡动作(不会硬切)。
完整的混合空间for move system:
调用混合空间:
在资产浏览器里拖出来, 用两个参数来控制它, 连接到输出口
目前我们可以自己在右下角的动画预览编辑器, 通过调节Angle和Speed的值来控制动画, 但是实际上在游戏里, 我们需要用角色的速度和转向角来作为输入, 去驱动BS_Locomation;
想要达成这个功能, 通常我们会选择使用事件蓝图来实现, 即使我们可以用C++实现(不推荐)
五. 事件图表(初级):
事件图表是一个动画系统的工具, 用来快速获取游戏角色的状态以及其他数据或者逻辑的工具;
在上面的动画蓝图中, 我们需要用角色的速度和转向角来作为输入, 去驱动BS_Locomation;
但是我们该如何获取到角色的实际数据呢?
想要达成这个功能, 通常我们会选择使用事件蓝图来实现, 即使我们可以用C++实现(不推荐)
1.理解基础的节点功能:
节点的接口有的是传值的, 有的是只进行执行(激活)的;
这种圆的接头是传值的, 不同颜色代表不同数据类型; 五边方型的接头是传递执行信号的;
节点:Event Blueprint Update Animation(蓝图更新动画事件)
它是干嘛的? 这是动画蓝图里的"心脏"。游戏运行后,它会**每帧(每一秒几十次)**不停地跳动。
为什么是灰色的(提示已禁用)?
UE 为了节省资源,如果你没有在这个节点后面连任何线,它就会自动进入"休眠"状态。
Delta Time X :这是两帧之间的时间差。新手暂时可以不用管它,它是给高级运算(如平滑过渡)准备的。
节点:Try Get Pawn Owner(尝试获取 Pawn 所有者)
作用: 返回此动画蓝图的使用者。
动画蓝图只是衣服(外壳),它必须穿在某个角色(Pawn/Character)身上。
这个节点的作用就是:"告诉我,是谁在穿这件衣服?"
返回值 (Return Value):
它会吐出一个"对象"。这个对象就是使用此动画蓝图的角色
节点:Is Valid (判空指针)
获取到角色指针后必须判空, 就和C++的if()判断一样
节点: SET (为变量设置数值float Speed = ?;)
获取角色的速度向量(速率和方向):
把Speed变量拖入空间, 然后选择设置Speed, 然后链接角色指针(判空后的), 如果发现指针非空, 就会执行SET速率Speed变量的操作, 然后就可以尝试一次读取速度的操作;
这里会尝试读取速率Speed, 但是读不到值, 因为还没传值进来, 白线是执行线, 我们需要绿线来传值进来;
节点: Get Velocity (获取速度向量=速度大小+速度方向)
节点: Vector Length (向量转标量)
不同数值接口颜色代表着不同数据类型, 这里是速度向量转为速度大小
最终效果:
节点: Inverse Transform Direction(逆向变换方向)
作用是:把"世界的方向"转变成"角色的主观方向"。
想象一下这个场景:
世界坐标: 地图的北方永远是固定不变的。
角色坐标: 角色的"前方"是随着角色转身而改变的。
问题来了: 游戏知道角色正在向"世界地图的北方"移动,但如果你不告诉 UE,UE 就不知道角色是在向前走、向后退还是向左侧滑。
如果角色面向北方走,那是"向前走"。
如果角色面向南方走,那是"向后退"。
如果角色面向东方走,那是"向左侧滑"。
Inverse Transform Direction 的工作就是: 拿着"世界速度方向",对比"角色面对的方向",最后吐出一个结果------"噢!原来角色正在往他自己的左边走!"
节点:获取玩家变换
它是用来获取一个物体在 3D 世界里的全方位状态信息 的。
Target(蓝色引脚):
含义: "目标",也就是"你想看谁的户口本?"。
通常连什么: 在动画蓝图里,这里通常连你之前看到的那个 Try Get Pawn Owner(也就是获取你的角色)。这表示:"我要获取我这个角色的位置和旋转信息。"
Return Value(橙色引脚):
含义: 返回的"变换"数据。
Location(位置): 这个物体在地图上的具体坐标(X, Y, Z)。
Rotation(旋转): 这个物体正对着哪个方向,斜了多少度。
Scale(缩放): 这个物体有多大,有没有被拉长或缩放。
节点: Rotation From X Vector(根据 X 向量生成旋转)
在虚幻引擎里,默认规定 X 轴是物体的"正前方"(也就是物体的鼻子或脸)。
这个节点的作用是:"如果我要让我的正面(X轴)对着这个方向,我该旋转多少度?"
可以展开:
最终效果:

六. 状态机的使用方式:
AnimGraph(总指挥部):就是你现在看到的这个大窗口。
State Machine(状态机/导演):你可以在这里放一个状态机。
State(状态/演员):比如你有一个"移动中"的状态。
Blendspace(混合空间/表演细节) :你会双击进入"移动中"这个状态,然后把这张图里的 BS_Locomotion 逻辑放进去。
动画蓝图 (ABP) > 状态机 (State Machine) > 混合空间 (Blend Space)
混合空间是对动画资产的排列组合和调用; 状态机是混合空间的调用者, 其状态节点就是对混合空间或动画蓝图的封装, 然后由状态机统一调度状态节点, 最后多个状态机之间的协作, 被统一成为一个动画蓝图, 所有的动画资产会根据这个蓝图调度
基础操作:
创建状态机:
添加状态节点:
右击空白处, 选择添加状态, 我这里命名为Grounded
点击此处退回到动画图表
设置状态节点
为状态机的状态节点添加动画, 这里以Grounded为例:
点击Grounded进入节点, 进入后, 会有一个Output Animation Pose, 这个东西本质上和之前做动画蓝图一样的, 连好线路后最终从这里输出:
我们直接把之前写的移动动作逻辑放入状态机中
设置状态切换:
我们实现这样一个功能:从地面跳到空中, 再从空中落到地面
地->空:新建一个Airborne空中状态, 然后链接两个状态, 然后可以点击这个圆形,进入切换状态规则的设置
Result的红色引脚代表着, 期待一个bool类型, 如果是真则会触发切换
我们可以创建一个IsAirborne的bool变量链接它;
空->地:
从Airborne画一根线到Grounded
进入切换规则节点后: 添加逻辑!运算符节点, 用于取反IsAirborne变量
七. 事件图表(进阶):
节点: sequence (信号拆分)
这个节点的作用是:把一个触发信号拆分成多路,按从上到下的顺序依次执行一连串动作。
为什么需要它?在 UE 蓝图里,一个白色箭头通常只能引出一根线。如果你想在"游戏开始"时同时做三件事(比如:1.给玩家加血;2.刷出怪物;3.播放音乐),你就需要用 Sequence 节点把这一路信号分成 Then 0、Then 1、Then 2 来按顺序完成。
节点: Try Get Pawn Owner
节点: Get Movement Component
节点: Is Falling
最终效果:
八. 状态机(进阶):
Locomation优化跳跃过程:
在地面和空中的两个阶段上多加几个过渡动画:
动画过渡优化:
状态节点之间的动画过渡也可以在 "状态切换节点" 的细节面板修改:
九. 叠加动画
叠加动画(Additive Animation)就是"在原有动作的基础上,额外增加一层微调动作",且不破坏原本的动作。
核心公式:最终效果 = 基础动作 + 叠加动作
基础动作(Base Pose): 就像你的全身衣服。比如你正在"跑步",你的全身骨骼(腿、胳膊、躯干)都在为了跑步而摆动。
叠加动作(Additive): 就像你戴的一根围巾 或一个发卡。它不管你是在跑步、坐着还是跳跃,它只负责在那儿产生一点额外的位移或晃动。
为什么要用"叠加",而不是直接做个新动作?
假设你正在做一个射击游戏,你希望角色在任何状态下都能有"呼吸"的效果(胸腔起伏)。
笨办法(不用叠加):
你需要专门制作"站立+呼吸"、"走路+呼吸"、"跑步+呼吸"、"蹲下+呼吸"......这会导致动画文件数量爆炸,工作量极大。
聪明办法(叠加动画):
你只做一个纯粹的、极短的**"胸腔起伏"**动画(这个动画里只有胸部骨骼在动)。
告诉 UE:把这个呼吸的"起伏"叠加到任何正在播放的动作上去。
结果: 无论角色是在跑、在跳还是在趴着,他都会自然地呼吸了。
它在技术上是怎么实现的?(数学原理)
这是叠加动画最神奇的地方:它存的不是"位置",而是"差值"。
普通动画(绝对动画): 记录的是"手现在必须在坐标 (10, 10)"。如果你播放它,手会强制跳到那个位置,不管之前在干嘛。
叠加动画(相对动画): 记录的是"手在当前位置的基础上,往上抬 5 厘米"。
如果手原本在腰部,播放叠加动画后,手会抬到腰部上方 5 厘米。
如果手原本在头顶,播放叠加动画后,手会抬到头顶上方 5 厘米。
常见的 3 个使用场景
呼吸/颤抖: 为各种静态或动态动作增加一点生动的细节。
受击反馈(Hit Reaction): 角色正在跑步,突然肩膀中了一弹。你可以把"肩膀猛震一下"的叠加动画加进去,这样角色会一边跑一边肩膀晃动,而不会打断跑步的脚步。
瞄准偏移(Aim Offset): 角色身体在往前跑,但手里的枪要随着玩家的鼠标上下左右转动。这个枪口的"上下左右偏移"就是叠加在跑步动作之上的。
如何使用叠加动画:
把Idle_AO_Combat添加到动画图表中:
然后在暴露出的接口中, Yaw表示偏航角, 我们已经在之前的Locomation中设置好了关于Yaw的动画,所以无需理会; Pitch表示仰角, 我们还没设置, 好在我们有叠加动画, 所以我们只需创建一个变量节点Aim Pitch给Pitch引脚传值就行了,然后在事件图表中将游戏角色的数据传入Pitch依赖的变量节点Aim Pitch;
事件图表中为Aim Pitch赋值
每个节点的功能:
Try Get Pawn Owner(尝试获取 Pawn 所有者):
功能:找到这个动画蓝图正穿在哪个角色身上。
Get Control Rotation(获取控制器旋转):
功能 :获取玩家相机(或者说控制器)在世界中指向的角度。
重点:这是玩家"眼睛"看的地方。当你动鼠标上下左右看时,这个值就在变。
Get Actor Rotation(获取 Actor 旋转):
功能 :获取角色身体在世界中面朝的角度。
重点:这是角色"胸膛"正对的方向。
Delta (Rotator)(旋转差值):
功能 :做减法。计算两个角度之间的差距。
计算公式:A (控制旋转) - B (身体旋转) = 相对角度。
SET Aim Pitch:
功能 :把算出来的结果里的 Pitch(俯仰角,即上下看的高度) 存到一个变量里,给后面的动画用。
为什么要用 Control Rotation 减去 Actor Rotation?
这是新手最容易困惑的地方。我们为什么要相减?
核心原因:获取符合动画蓝图范围的pitch
动画蓝图设计动画和pitch取值关系是是:
向上看 pitch = 0 ->90;向下看 pitch = 0 -> -90;
因为如果我们不减Actor Rotation,在默认情况下:
向上看Control Rotation返回的pitch值是0->90,向下看的pitch值是360->270而不是0->-90;
也许你还会有疑问, 既然一开始玩家朝向是0, 那你向下转90度, 用Control Rotation - Actor Rotation, 得到的应该是270 - 0 = 270;
Delta 节点的黑科技:
它是专门设计来对付这个问题的。当你用 A (350度) 减去 B (0度) 时:
普通的减法结果是 350。
但 Delta (Rotator) 节点很聪明,它知道你其实是在问"最短距离"。它会意识到 350 度其实就是 -10 度,所以它给你的返回结果会是 -10。
所以,即便 Get Control Rotation 给你的是 270-360,经过 Delta 节点计算后,你拿到的 Aim Pitch 依然会是正确的 -90 到 0。
这段逻辑最终实现了什么?
这段逻辑通常是为 瞄准偏移 (Aim Offset) 服务的:
Aim Pitch (Y 轴):存下这个值后,你会把它连到动画图表的混合空间里。
效果 :当玩家鼠标向上推 时,Aim Pitch 变大,角色的脊椎骨骼就会带动枪口向上抬 ;当玩家鼠标向下拽 时,枪口向下压。
九. 动画蓝图总览
动画蓝图 = AnimGraph(动画图表) + EventGraph(事件图表)
事件图表总览:

动画蓝图总览:

动画蓝图的Locomation状态机总览:

Grounded状态节点:

Jumpping状态节点:

Airborne状态节点:

Landing状态节点:






























































