文章目录
- PlayerStart 初始化
- 设置默认 Level
- BP_Character 初始化
- BP_Character 添加动画
- BP_Character 攻击
- BP_Enemy 初始化 以及 AI 运动
- Camera Collision 相机碰撞
- BP_Character 生命以及伤害
- Wave Spawner 波生成
- UI 初始化以及 Damage Screen
- 指定位置随机生成
- 添加声音
- 环境 Environment Level
- 替换 Character Asset
- 完结撒花
PlayerStart 初始化
PlayerStart 指的是角色出生点,也就是当前关卡中角色初始化时出现的位置
![](https://img-blog.csdnimg.cn/direct/3488cfa5853f4371bfdcb1e0badacc0f.png)
初始化角色由 Game Mode 指定,而关卡中的 Game Mode 由 World Setting 中的 Game Mode Override 指定
![](https://img-blog.csdnimg.cn/direct/b9298ecc714a4ef78a449f9c77f7e549.png)
创建一个 Game Mode 的 Blueprint GM_singleplayer
,将导入到 World Setting 中后,我们需要在 Game Mode 中去定义 Chracter,同时创建一个 Chracter 的 Blueprint BP_player
,将其导入到 GM_singleplayer
之中
![](https://img-blog.csdnimg.cn/direct/8882fd09e6e545b4af2c451845e02fe3.png)
这样 PlayerStart 的角色初始化完毕了
设置默认 Level
这里设置默认 Level 可以防止重新打开的时候是黑屏即没有默认关卡
![](https://img-blog.csdnimg.cn/direct/5992cb1fa6d0484daeaa3402baec98a7.png)
BP_Character 初始化
Mesh 指的是静态网格体,其基本操作设置如下所示,导入网格图,在 Transform 的 Mesh 中 location 的 z 设置为-89, rotation 的 z 设置为-90,用于调整网格体位置,使其与 capsule 对齐。
![](https://img-blog.csdnimg.cn/direct/20c9e87b5f0e462894a7ed6109a94508.png)
仅仅做这些还不够,这样并没有摄像头,我们并不能对视野进行移动,在游戏中我们可以使用 F8
跳出人物视口进行观察,与 ESC
不同的是,后者是直接退出游戏,前者是在人物视口和上帝视口进行切换。
![](https://img-blog.csdnimg.cn/direct/9e45f7c5c1674f5680204b6ed612d37c.png)
为此我们需要一个摄像头从人物外面观察,这里添加一个 SpringArm ,并在其中添加一个 Camera ,注意在 SpringArm 中,我们需要启用 Use Pawn Control Rotation,这可以接受输入并移动弹簧臂。
![](https://img-blog.csdnimg.cn/direct/1b1e06b4e45c4a789fff3c85dde63cf9.png)
现在可以在外面看到 Character ,目前存在一个问题,那就是无法控制 Character 的移动,在这里我们为 Character 添加移动功能。
首先在主目录创建一个 Input 文件夹,右键创建一个 Input Mapping Context,并命名为 IMC_PlayerInput
,这可以实现给输入做映射,相当于一个字典
![](https://img-blog.csdnimg.cn/direct/35ef483c261143b08fba5405b56bfa21.png)
那么有了字典,我们首先需要创建键,右键创建一个 Input Action,并命名为 IA_Move
![](https://img-blog.csdnimg.cn/direct/ab03754884e447539da759f5fac6dc43.png)
在这里 IA_Move
主要实现移动功能,包括前后左右位移,因此最好给 Input Action 设置两个维度的输入进而区别前后左右
![](https://img-blog.csdnimg.cn/direct/e2a9d4d93be44c458a740f34dc73678f.png)
回到 IMC_PlayerInput
,将 IA_Move
导入进去,然后添加激活按键 WSAD
,这里需要意识到的是,每一次激活按键只会改变一个值,默认是第一个值,IA_Move
中设置了一个二维变量,假设是 [ x , y ] [x, y] [x,y] ,从俯视图来看,这里定义 x x x 为横向(水平)运动, y y y 为竖向(垂直)运动。
![](https://img-blog.csdnimg.cn/direct/0a5ae5fc6cb04b1a8d8bc1f821a00df2.png)
其中 WS
设置为垂直运动对应 y y y ,那么我们需要将 x x x 和 y y y 调换位置,同时 W
与 S
应该是相反数,这里通过在 modifiers运用 Swizzle Input Axis Values
去调换 x x x 和 y y y 的位置;这里运用 Negate
去取相反数,同理对 AD
采取一致的操作。
![](https://img-blog.csdnimg.cn/direct/5029b7749c2348489c003a20979df2ba.png)
这样 IA_Move
设置在 IMC_PlayerInput
中设置完毕,接下来我们需要在 BP_Player
中使用 IA_Move
首先 Add Mapping Context
,把 IMC_PlayerInput
添加进去,这样我们就可以使用 IA_Move
![](https://img-blog.csdnimg.cn/direct/5ac014d52ac24033bbb745b719affbeb.png)
通过 IA_Move
定义移动,这里 Return Value Y(Patch)
不连,采取默认为0的方式,因为前后左右相对于 Character
来说默认是在 Patch 为 0 的情况即俯视的情况,所以这里不去链接。
![](https://img-blog.csdnimg.cn/direct/ee6c90daa6504c869048cbf06b7b45c9.png)
这里定义了 IA_Move
,还不能移动窗口方向,为此我们继续定义一个 IA_Look
,由于有 Yaw(左右)
和 Pitch(上下)
,因此同样定义为二维变量
![](https://img-blog.csdnimg.cn/direct/e080f38605b64f19b620649218c36ef9.png)
AI_Look
在 IMC_PlayerInput
相对容易定义,Mouse XY 2D-Axis
可以直接生成二位变量
![](https://img-blog.csdnimg.cn/direct/9be685ec6f054de399d128690ad4802d.png)
在 BP_Player
中,也比较好定义,利用两个 Add Input
可以实现 Add Controller Yaw Input
,Add Controller Pitch Input
。注意:如果不起作用,查看 SpringArm 中, Use Pawn Control Rotation 是否启用
![](https://img-blog.csdnimg.cn/direct/4d1dd1ba476e46aa9f359213ace54dba.png)
目前还存在一个问题,那就是人物一直朝前看,我们只能看见人物的背影
![](https://img-blog.csdnimg.cn/direct/3da5b6a63c2d44318d5997907c1a2f09.gif)
为此我们需要在 BP_Player
中设置两个东西,第一个是 Use Controller Rotation Yaw 设置为 False,这样我们在旋转窗口的时候,人物的朝向不会发生变化;
![](https://img-blog.csdnimg.cn/direct/c740f7a318614e06b3db21c5b3fae16d.png)
第二个是 Orient Rotation to Movement 设置为 True,这样在上帝视角和Character视角不一致的情况下,Character视角会运动到上帝视角。
![](https://img-blog.csdnimg.cn/direct/9c83e1d07e434a508e9463684b71c129.png)
问题修复如下
![](https://img-blog.csdnimg.cn/direct/8212587318bf4f01b7ba4e097f822a89.gif)
BP_Character 添加动画
目前人物都是滑行,没有动画,这里给 character 的静态网格体导入走路的动作
首先在 Animation
文件夹中创建 Animation Blueprint 文件,命名为 ABP_Player
![](https://img-blog.csdnimg.cn/direct/0187f59c6f274b9a9dda0f4b465c5461.png)
在右下侧 Asset Browser 窗口中将动画拖入到 AnimGraph
编译,就可以实现动画
![](https://img-blog.csdnimg.cn/direct/330945d2385d471f8f4cd4e0b6e35726.png)
接着我们在 BP_Player
中给 Mesh 添加 ABP_Player
![](https://img-blog.csdnimg.cn/direct/8ed46af13d5f4448bc07450213050b9e.png)
这样就可以给 Character 添加动画。为了使 Character 在不同的情况下如移动有不同的表现,在这里使用 Blend Space 对 动画进行混合
创建 Blend Space 1D 并命名为 IdleJogBlendSpace1D
![](https://img-blog.csdnimg.cn/direct/baf450b29df14b61b9777bdf29da9376.png)
在 IdleJogBlendSpace1D
中拖入 Idle,Walk,Run这三个动画,并移入到时间轴中
![](https://img-blog.csdnimg.cn/direct/7c83a699b7024ead921220151102ef55.png)
同时,在这里我们需要定义一个变量去控制这三种状态转换,这里定义变量名为 Speed ,这里的最小值和最大值表示变量的区间,很好理解,Smoothing Time 表示动作之间的切换时间,一般设置为0.2足够。
![](https://img-blog.csdnimg.cn/direct/8ad7841842e14092a6c96e87964afe9a.png)
这里 IdleJogBlendSpace1D
就设置完毕了,IdleJogBlendSpace1D
其本质上依然是一个动画,因此我们需要在动画蓝图中导入,打开 ABP_Player
,在 AnimGraph
中将 IdleJogBlendSpace1D
导入,并将 Speed
提升为变量
![](https://img-blog.csdnimg.cn/direct/8342be8622a84b51b797684230639a6a.png)
连接 Speed
,得到如下蓝图
![](https://img-blog.csdnimg.cn/direct/2f364f4ec03a4baabcd13be39cbec18e.png)
然后在 Event Graph 中获取 Pawn 的速度 velocity,由于速度是三个维度向量,我们需要使用 Vector Length 将向量转化为 1D标量速度
![](https://img-blog.csdnimg.cn/direct/b1f1a031ce5e4fce9131649fd715e4d8.png)
ABP_Player
设置完毕,运行可以发现可以自由运动,并且动画很流畅
![](https://img-blog.csdnimg.cn/direct/e8ba837feeda4a97802ea6ccf05c3fa9.gif)
BP_Character 攻击
和 BP_Character 初始化一样,我们需要给攻击添加输入,在 Input 下创建 IA_Attack
![](https://img-blog.csdnimg.cn/direct/2a1a02593df5490193f6135541a7a137.png)
在Attack中,我们只需要有简单的判别功能来判断是否按键,因此,IA_Attack
的 Value Type 只需要设置为 Digital(bool)
![](https://img-blog.csdnimg.cn/direct/1f8237ecc1cb408f96706d25d3b15315.png)
同时,将 IA_Attack
添加到 IMC_PlayerInput
中,并设置鼠标左键作为输入
![](https://img-blog.csdnimg.cn/direct/3ecc97d97f974ef9ae1f9f87511ce1e0.png)
现在输入搞定了,接下来便是动画部分,这里我们使用 Mixamo 中的动画,这里以踢腿的动画为例子
![](https://img-blog.csdnimg.cn/direct/813e71214e4546c9b151976fb9ffd88e.gif)
按下面要求下载,这里保留 Skin
方便后面操作
![](https://img-blog.csdnimg.cn/direct/bfed9ec18bca41a2a512a16669c89035.png)
下载完毕后,在 Characters 目录下新创建文件夹,这里以该任务模型的名字命名 MMA,导入 FBX 文件的静态网格体 Mesh 和动画 Animation
![](https://img-blog.csdnimg.cn/direct/d880d5ffbc7f4743baaf9dca7992684a.png)
这里要注意,记得导入动画,默认是不导入的 Import Animations
![](https://img-blog.csdnimg.cn/direct/e577564df72746d7a090a9abf993ba41.png)
创建四个文件夹,将导入的文件分类整理好
![](https://img-blog.csdnimg.cn/direct/0bfd320163574a3b9b9adc981498fec8.png)
打开 Animations
文件夹,可以发现动画 Animation Sequence 是绑定在 MMA 的骨骼上的
![](https://img-blog.csdnimg.cn/direct/aac81e7135dd4911aa495725734bd264.png)
为了让 UE5 小白使用该动作,我们需要对该动画进行重定向 Retarget Animations
![](https://img-blog.csdnimg.cn/direct/8fdf8dc1841b4166baeb04924481ca20.png)
导出到UE5小白的动画文件夹,打开可以看到效果很好
![](https://img-blog.csdnimg.cn/direct/f28677a8d12d4d3c9d376e4e935e9050.png)
该动画有缺点,即攻击动画速度要快和准,这样的动画前摇和后摇太长,因此我们需要对动画去帧处理,然后可以在 Rate Scale 中调整播放动画的速度
![](https://img-blog.csdnimg.cn/direct/229bb86885254aad923dabf504fd3129.png)
处理后得到符合要求的动画,在 BP_Player 中使用该动作之前,我们需要了解 Play Animation 和 Play Montage 的区别:简单来说,前者播放动作后不能复原到默认状态,而后者 Play Montage 可以,因此我们应该将动画 Animation Sequence 转化为动画蒙太奇 Animation Montage
![](https://img-blog.csdnimg.cn/direct/9676e48dfda44d60a674860777d3edee.png)
Montage 类似于 Blend Space,可以拖入多个动画,Montage可以绑定多个事件进行操作
![](https://img-blog.csdnimg.cn/direct/505268f6a2e94144bc825d684d88397b.png)
ok,输入和动画全部搞定,接下来在 BP_Player
中结合输入和动画
![](https://img-blog.csdnimg.cn/direct/3811c496d8ee4c0b8ff8d443d9f12d33.png)
设置完毕至目前应该是无效果的,因为 Montage 需要在 AnimGraph 中有一个 slot 才可以使用,这里回到 ABP_Player
,在 AnimGraph 中设置 DefaultSlot
![](https://img-blog.csdnimg.cn/direct/f8dc06790b414b4abba5809097a32ffb.png)
动画搞定,看效果,这里要提到的是,如果要实现 Play Montage 的同时移动,需要禁用 Animation Sequence 中的 EnableRootMotion,默认是禁用了的;如果要实现 Play Montage 时移动失效,并使用 Montage 的 Root 移动,需要启用Animation Sequence 中的 EnableRootMotion
![](https://img-blog.csdnimg.cn/direct/2fb9a0ccbc79411ca655dbb4247c6cc6.gif)
由于是攻击,有碰撞判定,接下来设置判定的位置和时间,判定的位置我们可以在 BP_Player
中使用 Arrow 来调整
![](https://img-blog.csdnimg.cn/direct/344322c0de804b3297cd4c38b5bb47ac.png)
判定的位置设置如下
![](https://img-blog.csdnimg.cn/direct/e04f2152bdf744aebf112a3ca96e8a1a.png)
判定时间有两种方式,第一种是采用延迟的方式,即 Delay
;不过这种很难调整;第二种是使用 Montage notify 的方式,在 Montage 上设置 notify 如下;
![](https://img-blog.csdnimg.cn/direct/701f682f70544118b8726402188a6192.png)
设置完毕 notify 后,直接将 On Notify Begin 与 Multi Sphere Trace for Objects 连接
![](https://img-blog.csdnimg.cn/direct/73c9006866a947cbb050c223c48b2f99.png)
此时设置完毕了,效果如下
![](https://img-blog.csdnimg.cn/direct/44807bb5001d4a9d8c64f61bee29b1a7.gif)
BP_Enemy 初始化 以及 AI 运动
BP_Enemy 类似于 BP_Character,不同的是,由于我们不需要从 enemy 本身进行观察,因此我们不需要设置 camera 以及 springarm
导入 Quinn 的 mesh, 并设置 mesh 的 location,同时设定 Animation ,这里设置和 BP_Player 一样的蓝图
![](https://img-blog.csdnimg.cn/direct/552ed6166cde4f25aaf9c9c6b1f45b9e.png)
现在 BP_Enemy 已经初始化,接下来开始为 BP_Enemy 添加 AI 运动功能,wonder 以及 chase
在执行AI运动功能之前,我们需要先导入一个寻路网格体,NavMeshBoundsVolume,并把大小调整至足够大
![](https://img-blog.csdnimg.cn/direct/96613c1131e741ddb027128cce6f2195.png)
有了寻路网格体,这样 BP_Enemy 才能运动到指定位置,同时在面对转向动作时,我们依然要记得把 Orient Rotation to Movement 设置为 True,这样可以避免突然转向
![](https://img-blog.csdnimg.cn/direct/43f7f9bf3901446d831273eda97330d6.png)
Use Controller Rotation Yaw 由于不需要控制 BP_Enemy ,所以是可以关可以不关的状态,不过最好还是关掉
![](https://img-blog.csdnimg.cn/direct/ef704a9b216f47b1b2106845fe41f1ff.png)
接下来实现 wonder 事件
![](https://img-blog.csdnimg.cn/direct/55d29b9c86904668b4263233d87ffc35.png)
效果
![](https://img-blog.csdnimg.cn/direct/6130f2db9c6945f5bd0a00a502cfba90.gif)
然后实现 chase 事件
![](https://img-blog.csdnimg.cn/direct/14eecba99c3547ca81e4d6063315c0e3.png)
效果
![](https://img-blog.csdnimg.cn/direct/b9cdfb37f87243e58bef0535dd23c287.gif)
最后直接把事件绑定在 Event BeginPlay 上就行,当然最好把 max walk speed 调整为较小值
![](https://img-blog.csdnimg.cn/direct/4701fb8159d94fc1967b188accb33e83.png)
Camera Collision 相机碰撞
在两个 Character 碰撞时,可能会导致相机出现抖动,我们需要在 Character 的 Blueprint 中 设置两个 coliision,分别是 Mesh 的 collision 以及 CapsuleComponent 的 collision
![](https://img-blog.csdnimg.cn/direct/be74e4d56e8d43ae8dd4c7a3d6e20c04.png)
在设置 camera 为 Ignore 后,碰撞问题就解决了
BP_Character 生命以及伤害
首先设置生命 Health,数据类型设置为 浮点类型 Float,然后设置一个默认值,这样生命就设置完毕了
![](https://img-blog.csdnimg.cn/direct/8d636db782f645abaed462e80bd70e3c.png)
伤害分为施加伤害以及收到伤害,首先是施加伤害,施加伤害的目标首先是需要检测的,在 BP_Character 攻击中我们使用了 Sphere Trace For Objects 来检测目标,然后判断是否命中 Apply Damage 即可,同时设置上海数值
![](https://img-blog.csdnimg.cn/direct/f51e6de54f4c43b1958fc91c72c9b8ab.png)
收到伤害后,我们使用 Event AnyDamage 来接受伤害
![](https://img-blog.csdnimg.cn/direct/ea8910cfbf2a49d6ae010beac699957a.png)
然后将伤害系统移植到 BP_Player 和 BP_Enemy 上,在 Chase 中,要注意循环是添加在 Montage 播放完毕之后的
![](https://img-blog.csdnimg.cn/direct/b14f3814070e42ba87209e797b32ee96.png)
Wave Spawner 波生成
首先我们创建一个 BP_Actor 蓝图命名为 BP_WaveSpawner
来创建 Enemy 生成点
![](https://img-blog.csdnimg.cn/direct/e5512fba9d814c58ab4f33d428bc8ec0.png)
双击打开 BP_WaveSpawner
,为了让 BP_Actor 可视,添加一个 Sprite,Billboard,这是一个使图片能在任何角度正面朝向视角的 component,放置的时候要注意高度,不然生成的 Enemy 可能会卡在墙里
![](https://img-blog.csdnimg.cn/direct/04c11f2dbb074069b02e0d8ffe765bbc.png)
然后实现一个基本的 spawner 使其能生成 BP_Enemy,注意这里可能会生成多个,在 Collision Handling Override 设置中设置为 Try To Adjust Location, But Always Spawn
![](https://img-blog.csdnimg.cn/direct/34d1d51804284370b4b23c94a74b78c1.png)
但是光这样生成的 Enemy是 AI运动 不了的,我们需要在 BP_Enemy 中的 Auto Possess AI 中选择 Placed in World or Spawned
![](https://img-blog.csdnimg.cn/direct/6a561140b6b24c51854b838a6d019598.png)
这样使用 spawn 生成的模型也可以 AI运动
![](https://img-blog.csdnimg.cn/direct/4d3c399ed8614ae59265014e41229f88.gif)
现在要实现植物大战僵尸一样的效果,击败每一波敌人后会出现下一波敌人直到通关
首先我们定义一个函数生成指定数量的敌人
![](https://img-blog.csdnimg.cn/direct/319afa4d2abe425294281ba25606d5be.png)
然后生成一个数据变量设置每一波 Enemy 数量
![](https://img-blog.csdnimg.cn/direct/19ecc503a3b54b0787563d22d58d1a36.png)
创建当前波的生成事件,然后使用 Event BeginPlay 生成事件
![](https://img-blog.csdnimg.cn/direct/3e7b45284db9488c86cc4379352261d9.png)
在 BP_Enemy 的 Event AnyDamage 事件中判断敌人数量并生成当前波,为此延迟三秒 Destroy BP_Enemy 重新计算所有BP_Enemy 数量,当数量为 0 的时候生成当前波
![](https://img-blog.csdnimg.cn/direct/72d8cafe54284d79a95f2319fec2b525.png)
得到效果如下
![](https://img-blog.csdnimg.cn/direct/d5a984951b1744c79484d8878590c0d3.gif)
UI 初始化以及 Damage Screen
首先创建一个 Widget Blueprint,命名为 WB_HUD
,当然我们可以将其分开,例如我们可以创建小部件 WB_HealthBar
![](https://img-blog.csdnimg.cn/direct/bc17ec26e9b94756ad088468e6e71068.png)
打开 WB_HealthBar
,首先添加一个 Canvas Panel,可以在上面添加东西
![](https://img-blog.csdnimg.cn/direct/d3eb086c23ed44008710ffb734b7a878.png)
在 Canvas Panel 上添加一个进度条
![](https://img-blog.csdnimg.cn/direct/cfd5305926434be0964f7b1f70d5ede5.png)
接下来我们绑定这个 HealthBar,有两种方式,第一种是进入右上角蓝色框 Graph
中设置函数并设置返回值然后回到红框进行绑定,第二种是通过红色框点击 bind ,Create Binding 创建函数进行绑定。
![](https://img-blog.csdnimg.cn/direct/0642e0d97832444ea8419ac26c9d2f23.png)
函数中操作如下
![](https://img-blog.csdnimg.cn/direct/2cf2b601ac1b4998ad93215c410737d6.png)
Widget Blueprint 绑定完毕如下
![](https://img-blog.csdnimg.cn/direct/8dab68cc2e3b45e5a6278e04e1c55f72.png)
接着我们可以创建一个收到伤害效果,这里继续创建 Widget Blueprint,命名为 WB_HUD
,在上面添加 Canvas Panel 加入 Image
![](https://img-blog.csdnimg.cn/direct/e331f4872a004932853b4ba0b00cd82c.png)
然后在 Appearance 中设置颜色
![](https://img-blog.csdnimg.cn/direct/2d71516b607947cca089ff6a937b9ed5.png)
设置完毕后,我们可以添加动画,点击最上方的 window 选择 animations,就会出现动画窗口
![](https://img-blog.csdnimg.cn/direct/e5317c50f276486aa668b0e7e729a15d.png)
设置动画,并设置动画名称为 DamageScreen
![](https://img-blog.csdnimg.cn/direct/b17125bdad204df2b15b3f0ab2d5a674.png)
动画设置完毕后,点击右上角的 Graph 回到 Graph 页面,创建一个自定义事件 Damage Screen
![](https://img-blog.csdnimg.cn/direct/4549419eaf99404993ca1945239551ee.png)
接着在这里实现文字功能来显示第几波,回到 Designer 页面,添加文本
![](https://img-blog.csdnimg.cn/direct/916a7c1e40574aa5815a8ddd8e7dec97.png)
在 Appearance 的 Justification 中居中
![](https://img-blog.csdnimg.cn/direct/383bb566ef7945039fc66ba148aa614e.png)
然后点击绑定 Text
![](https://img-blog.csdnimg.cn/direct/17024cd981504193bc8fb368568151ac.png)
实现函数如下:
![](https://img-blog.csdnimg.cn/direct/2898fd6536ea420a88bc12f7fd8e0d60.png)
然后将两个 Widget Blueprint 添加到 Viewport 中,这里我们可以将两个 Widget Blueprint 添加到 BP_Player 中
WB_Health
没有触发事件是最简单的,直接在 BP_Player 的 Event BeginPlay 中 Create Widget ,然后 Add to Viewport 就好
![](https://img-blog.csdnimg.cn/direct/7a87a684979243aebe2d4c1daf2e98db.png)
接下来是 WB_HUD
,由于里面包含一个动画触发,所以我们需要将 HUB 设置为一个变量,然后再添加到 Viewport
![](https://img-blog.csdnimg.cn/direct/a8ca14e2047a4b66a086384d5e4889cd.png)
然后将 Damage Screen
添加到 Event AnyDamage 中
![](https://img-blog.csdnimg.cn/direct/0f7a0c9b54274c938415926bf9c63011.png)
实现效果如下
![](https://img-blog.csdnimg.cn/direct/3b53eb3b787c47c981ccfdd0d922906f.gif)
指定位置随机生成
我们在 BP_WaveSpawner 中设置一个 Spawn Position
![](https://img-blog.csdnimg.cn/direct/b20dd07741f4415baeed3dad057f2b7c.png)
然后在关卡中设置其默认位置
![](https://img-blog.csdnimg.cn/direct/c59a8a8ebfa748d0b34e757afbcdae2f.png)
搞定
添加声音
这里有五个声音,下载下来
Footstep: https://freesound.org/people/swuing/s…
Attack Grunt: https://freesound.org/people/MrFossy/…
Damage Grunt: https://freesound.org/people/whisperb…
Wave Completed: https://freesound.org/people/Kenneth_…
Forest Sounds Looping: https://freesound.org/people/rolandas…
在 Content 目录下创建 Audio文件夹,把声音文件放进去
![](https://img-blog.csdnimg.cn/direct/6271338e516745068ad13973a861bc87.png)
重复性的音频会让人感到无趣,我们可以使用 MetaSound Sourse 使音频动态随机变化
![](https://img-blog.csdnimg.cn/direct/59b9e76bf747410790c87f07e7cf66d5.png)
用随机值 random float 去调整 Pitch Shift
![](https://img-blog.csdnimg.cn/direct/d9625d677bb8483c8bee42e628786011.png)
现在的声音并没有距离范围,即目标在很远如果贴上了这个声音一样可以听见,我们可以给声音添加一个3D效果,创建一个 Sound Attenuation
![](https://img-blog.csdnimg.cn/direct/a0bd003d9e92456684fcb72e7422db78.png)
在 Sound Attenuation 中设置 Inner Radius 和 Falloff Distance
![](https://img-blog.csdnimg.cn/direct/430cfdd34d60426c9b48033b73e2ccc6.png)
然后将 Sound Attenuation 运用到 MetaSound Sourse,即 SA_Character
运用到 MS_Footstep
![](https://img-blog.csdnimg.cn/direct/d55dc1a7a5f542339a4cb476e3b561dc.png)
衰减 Attenuation 已经做了,接下来我们把声音加到动画上,我们回到 Animation Sequence 上,这里走路的 Animation 有 walk,run 我们在其下脚的时间帧上添加声音
![](https://img-blog.csdnimg.cn/direct/c3639ca753ca4c76ada9fe0659738c14.png)
将 Play Sound 的 detail 的 Sound 切换成 MS_Footstep
![](https://img-blog.csdnimg.cn/direct/ba15246da3044dc58727a43986f3870e.png)
这样脚步声就添加完毕,现在添加攻击以及受伤的声音,由于攻击有动画,所以其设置和 Footstep 一样,将声音用MetaSound Sourse 包装后直接添加到动画中
受伤是没有动画的,在将受伤音效包装完毕后,我们是直接添加到 BP 之中,首先是 BP_Player
![](https://img-blog.csdnimg.cn/direct/d10b4f71b2944c58bccb5d42c888b9ef.png)
然后是 BP_Enemy
![](https://img-blog.csdnimg.cn/direct/af7d4251375a44509491b9f3ed73ca94.png)
攻击和受伤的声音添加完毕了,然后我们来添加切换 Wave 的声音,这里的声音可以不发生变化,不需要使用 MetaSound Sourse 来包装,同时这里由于不涉及到距离的关系,可以直接使用 2D 来播放
![](https://img-blog.csdnimg.cn/direct/166d0bc813d0469fbf425f74d5b5a3a1.png)
这里受伤的声音太大了,我们可以在MS_Damage 中调节音量的大小,这里调节为原来的一半
![](https://img-blog.csdnimg.cn/direct/74aab2ab4b3f425b82371427c7295371.png)
环境 Environment Level
这里导入免费资产 Stylized Nature Pack
![](https://img-blog.csdnimg.cn/direct/421e26fb59df44e881f430c8e8d33397.png)
重新打开项目,可以看到
![](https://img-blog.csdnimg.cn/direct/ed0f211844464b988bf1dfd7bcb0441b.png)
我们首先进入 Level 文件夹,直接复制 Testing 重命名为 WavesMap
然后删除 Floor,即地板,因为我们要重新创建一个 Landscape
![](https://img-blog.csdnimg.cn/direct/a0ef57e961394e4dad70ac086377663a.png)
接着我们点击 Selection Mode 切换至 Landscape Mode
![](https://img-blog.csdnimg.cn/direct/025f91527b974dad9454985be7f75ba3.png)
这里 Enable Edit Layers,同时 Section Size 设置为 31 x 31 效果要好一些,然后直接创建就行
![](https://img-blog.csdnimg.cn/direct/9105e894e15a472eba5ba9b5c8b4de5c.png)
创建完毕后,可以看到 Landscape 光溜溜的什么也没有,是因为 Landscape 是图层的组合,这里我们需要应用图层,因此我们打开 Paint ,设置 Layers
![](https://img-blog.csdnimg.cn/direct/908003d09458483e8aaedfc1e9a62e1b.png)
返回 Selection Mode,得到 Landscape 效果如下
![](https://img-blog.csdnimg.cn/direct/38f0678261ac4bd48afa6ad8b149f5ba.png)
然后回到 Landscape Mode ,我们利用 Sculpt 来创造一些小山
![](https://img-blog.csdnimg.cn/direct/8c1d29a4ad92426a890cb19b0a10ee39.png)
创建完毕后,我们切换 Landscape 进入 Foliage Mode,在这里我们添加一些 Foliage
![](https://img-blog.csdnimg.cn/direct/a91e2e9c15994154b807da2c16802de7.png)
将 FoliageTypes 的植物分批次 Paint 在 Landscape 上
![](https://img-blog.csdnimg.cn/direct/5a8f1cd2c5414beeafc6215dfa45f2b9.png)
同时可以调整 Foliage 的大小和密度
![](https://img-blog.csdnimg.cn/direct/7a840a1ac2b74e7385da36168e79c6d3.png)
创建完毕 Foliage 之后,我们开始添加草,草使用 Landscape 来创造更好,返回 Selection Mode,在 Stylized_PBR_Nature 文件目录下创建一个 Landscape Grass Type,命名为 LG_Grass
![](https://img-blog.csdnimg.cn/direct/f84d624356b647aca4b1682206dc6df5.png)
打开 LG_Grass
,设置 Grass Mesh,Grass Density,Cull Distance
![](https://img-blog.csdnimg.cn/direct/5edce2b1184f41e18a164d542243e520.png)
然后,选择 Landscape 中的 Landscape Material
![](https://img-blog.csdnimg.cn/direct/04a1534667c04579a3ad8ccf210567ee.png)
进入 Landscape Material,添加 Landscape Layer Sample,并连接 Landscape Grass,Landscape Grass 中设置为 LB_Grass
同时要保证 Landscape Layer Sample 要和 Landscape Layer Blend 中 Layer Grass_01 一致
![](https://img-blog.csdnimg.cn/direct/05a15568f41741f3ac94fce45d55b84a.png)
返回 Level,可以得到效果如下
![](https://img-blog.csdnimg.cn/direct/984e5107eeec4c2f9fa964ee3683c78f.png)
草地成功添加进去,同时可以看到 Foliage 可以随着风飘动,这里可以设置风的速度,在材质 Material Instance 里面
![](https://img-blog.csdnimg.cn/direct/2dd4caadaebb4fdd9d13bb7534bebbd7.png)
这里颜色需要调整,我们可以使用 PostProcess Volume 对颜色进行后期处理,首先添加 PostProcess Volume
![](https://img-blog.csdnimg.cn/direct/b6d025386c97430f991c5341c03d0d6a.png)
启用 PostProcess Volume 中的 Infinite Extent,可以让范围不局限于小方块之中
![](https://img-blog.csdnimg.cn/direct/74ec433ee5374518aaf2b3b1a0132a9f.png)
然后在 Exposure 中 调整 Min Max EV100,分别位置为1
![](https://img-blog.csdnimg.cn/direct/689926bef89b4df9af243ec06f160f8c.png)
在 Global 中 设置饱和度和对比度 Saturation ,Contrast
![](https://img-blog.csdnimg.cn/direct/e553af2acbda4cf18e49d09e10889fbc.png)
然后调整直射光 DirectionalLight
![](https://img-blog.csdnimg.cn/direct/50ad8b315737415eb7003b1a7a414be8.png)
颜色问题处理完毕,接下来是 Nanite,启用和禁用 Static Mesh 的 Nanite 功能如下
![](https://img-blog.csdnimg.cn/direct/65f33e658b7441ae976faea2c030eec9.png)
对比是否启用,可以观察到启用 Nanite 的效果要比不启用的效果更绿
![](https://img-blog.csdnimg.cn/direct/11d2263e02e448359afccf3fffc04c62.png)
最后还有树的碰撞部分,从严格意义来讲是 BlockAll 形式,直接设置就好
![](https://img-blog.csdnimg.cn/direct/82a2f2c6da244c029b7f63617c69e39d.png)
环境部分结束
替换 Character Asset
这里导入 Stylized Character Kit: Casual 01 上面的资产工程文件
![](https://img-blog.csdnimg.cn/direct/6773084a7d8b4fdea42a3eeaf08eb8a2.png)
由于这里的人物模型是根据UE4定做的,所以这里我们进行一次重定向 Retarget
![](https://img-blog.csdnimg.cn/direct/c4e46dab146b4123a5261050a2f72445.png)
然后使用新的 Mesh 和 新的动画蓝图 ABP_Player,这里由于 Attack 的动画不在 ABP_Player 上,我们要对其单独重定向
![](https://img-blog.csdnimg.cn/direct/8598d813a22840db931685114a2df040.png)
然后在 BP_Player 中设置,首先是 Mesh 和 Animation
![](https://img-blog.csdnimg.cn/direct/2b5e9167332e40d18f063d9b3b011ace.png)
然后是 Attack
![](https://img-blog.csdnimg.cn/direct/83740762ef06466f80cc56ca29ef315a.png)
敌人可以设置为随机的 Mesh,首先在 BP_Enemy 中创建 Skeletal Mesh Array,然后导入 Mesh 设置 Mesh
![](https://img-blog.csdnimg.cn/direct/84caa54924454d00a1b8c295cbe4a004.png)
但是这里还会出现一个 BUG,那就是 Mesh 无法 simulated physics,因为这些 skeletal mesh 没有 physics assets,在create and assign physics assets之后,就可以正常 simulated physics 了
![](https://img-blog.csdnimg.cn/direct/d774a483d67d40fba362e7ce5a6a942b.png)
游戏效果如下
![](https://img-blog.csdnimg.cn/direct/88546beee2a747279de524a14f573a66.gif)
可以添加背景音乐,可以直接循环拖入游戏中,首先打开背景音乐 Forest_Sounds_Looping,启用 Loop
![](https://img-blog.csdnimg.cn/direct/29aa5ad42d2b412c81d61f615e241ba5.png)
然后拖入游戏中
![](https://img-blog.csdnimg.cn/direct/6d656d1794674198a183d6ed9c52e2f6.png)
到此,游戏已经完成 !!
完结撒花
耗时两天半!!