UE5FPS游戏开发教程(四)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

一、换弹系统

1.制作换弹系统(上)

下面我们来制作换弹系统。换弹系统一共分为两层,一个是表现层,一个是逻辑层。表现层就是换弹动画、换弹音效等等负责表现的东西。逻辑层就是换弹后玩家还剩多少子弹,什么时候才能换弹等这样的逻辑。

下面我们先来实现表现层。

我们在Input文件夹中创建一个输入操作IA_Reload,用来表示换弹输入,即当按R按键时就换弹。它的值类型就是布尔。

然后我们打开IMC_FPSInput,然后添加一个IA_Reload的输入映射,设置映射为按键R。

然后在BP_FPSPlayer角色蓝图中,添加IA_Reload事件。

然后在BP_WeaponBase蓝图中添加一个自定义事件命名为Reload,这个事件就是换弹事件。

然后我们在BP_FPSPlayer蓝图的IA_Reload事件的Started引脚后通过CurrentWeapon对象执行BP_WeaponBase蓝图中的Reload换弹事件。

IA_Reload事件的Started引脚后表示按一次R键就可以换弹了,不需要一直按着R键。Triggered引脚后需要一直按着。

然后我们找到Player玩家的Reload动画资产,然后右键创建动画蒙太奇,然后打开新创建的动画蒙太奇,然后设置它的混出中的混出时间为0.5;比率范围为1.5,这个比率范围就是动画播放的快慢,我们让它播放快一些;然后选中最长的动画轨道,在右边设置它的结束时间为2.88,因为这个动画在2.88时就播放完了。

然后我们再找到维克多的Reload动画资产,同理创建动画蒙太奇,然后进入动画蒙太奇进行设置。

然后我们在BP_WeaponBase蓝图的Reload事件后创建两个播放蒙太奇节点,分别播放角色手臂换弹动画和武器换弹动画。然后我们将两个播放蒙太奇节点的骨骼分别设置为Weapon和Player对象中的Arm,然后再分别选择角色手臂换弹动画蒙太奇和武器换弹动画蒙太奇。

此时运行项目按R键就可以播放换弹动画了。

下面我们来给武器也创建一个状态枚举,因为随着项目的完善,可以体会到武器的状态现在也有开枪、换弹等多种状态了,并且这些状态有的相斥,即换弹的时候不能开枪。所以我们在Enum文件夹中再创建一个枚举值,来记录武器的当前状态。

然后打开武器状态枚举E_WeaponState,然后设置三个枚举值,分别为Idle站立、Firing开火、Reloading换弹。

然后我们在BP_FPSPlayer的IA_Fire事件后将设置IsFiring为true的节点删除,然后我们需要将设置IsFiring的逻辑放到BP_WeaponBase蓝图的StartWeaponFire事件的创建定时器后面。因为在BP_WeaponBase蓝图的StartWeaponFire事件后先判断了当前武器有没有子弹,即是否满足开火条件,如果满足了才设置开火状态。而之前在BP_FPSPlayer蓝图的IA_Fire事件后面没有对开火条件进行判断,所以我们更改IsFiring变量的设置位置。

然后我们在BP_WeaponBase蓝图中创建一个E_WeaponStart类型的变量WeaponState,然后在StartWeaponFire事件后先判断当前WeaponState值为Idle时才允许开火。

然后在判断成功开火后设置WeaponState的状态为Firing。

然后我们在StopFire事件后先判断WeaponState的状态为Firing或Idle时才能执行后面的停止开火逻辑。然后在停止开火后再设置WeaponState的状态的Idle。

然后我们在Reload换弹事件后先判断武器WeaponState的状态为Idle空闲时才可以执行换弹操作,然后在换弹之前还要判断当前弹夹子弹余量小于弹夹总容量,并且子弹总余量不为0,只有满足这两个条件了才允许执行换弹逻辑。然后我们将WeaponState的状态设置为Reloading,表示当前正在换弹状态。然后当角色手臂换弹动画和武器换弹动画播放完成后或中断后,再设置WeaponState的状态为Idle空闲。因为角色手臂换弹动画和武器换弹动画的时长一致,所以我们在哪个动画的完成时后面设置WeaponState的状态为Idle都可以。如果两个动画的时间不一致的话,那么我们就需要在最长的动画的完成时引脚后面设置WeaponState的状态为Idle。

然后我们在BP_VIRTUS蓝图中设置维克多枪的当前弹夹子弹数量小于30,这样才能执行换弹逻辑。

此时运行项目,按下R按键,武器就可以换弹了。并且开火的时候按R按键是没有反应的,换弹的时候开火也是没有反应的。

2.制作换弹系统(中)

下面我们来添加换弹音效。

我们在BP_WeaponBase蓝图的Reload事件后面添加一个播放音效2D节点,然后设置它的资产为Reload音效。然后我们双击打开Reload音效,设置它的音量为0.57,音高为1.5,这样换弹声音就不至于过大了。

此时运行项目,按R按键换弹时,就会播放换弹音效了。

3.制作换弹系统(下)

下面我们来制作换弹系统的逻辑层。

我们先来解决一个bug。当我们运行项目,然后一直不开枪,然后点击换弹时,就会出现bug。然后停止项目,此时会报错误Player为空。

这是因为我们在BP_WeaponBase蓝图中的StartWeaponFire事件后给Player变量赋值的,所以当不开火时,BP_WeaponBase蓝图中的Player变量就为空,所以点击换弹时Player就为空了。

此时我们可以在BP_WeaponBase蓝图的Reload事件后使用到Player变量的地方,将它的引脚连接到Reload事件上,此时可以看到Reload事件上就有一个类型为BP_FPSPlayer的输入值了,然后我们在Reload事件后也设置Player变量对象。然后我们在BP_FPSPlayer蓝图的IA_Reload事件后,创建一个Self节点传递到BP_WeaponBase蓝图对象的Reload事件的输入值上。这样这个Bug就解决了。

然后我们在BP_WeaponBase的FireInternal事件后面让变量CurrentAmmo当前弹夹子弹余量减减,即每循环执行一次开枪定时器,就让当前弹夹子弹余量减1。

然后我们在FireInternal事件刚执行时判断变量CurrentAmmo,当CurrentAmmo大于0时才继续执行后面的开枪逻辑;当CurrentAmmo小于等于0时就执行停止开枪事件。这里停止开枪事件的目标要连接为Player对象。

然后在前面的判断CurrentAmmo变量是否大于0的地方,当CurrentAmmo变量不大于0时,就创建一个播放音效2D节点,然后设置一个枪械撞针音效来表示弹夹没有子弹了。

然后我们在BP_WeaponBase蓝图中创建一个Reload_Ammo函数,在该函数中完成换弹判定和子弹数量计算逻辑。

我们先通过MagSize(弹夹最大容量)减CurrentAmmo(当前弹夹子弹余量)得到当前弹夹还差多少发子弹就满了,然后再通过TotalAmmo(总弹余量)判断当前总弹余量是否大于还差的子弹数量,如果大于的话,那么就说明TotalAmmo(总弹余量)能把弹夹上满子弹。然后就执行后面的逻辑,即先让TotalAmmo(总弹余量)减去上的子弹数量得到当前的总弹余量,然后再设置CurrentAmmo的值为MagSize,即上满子弹后当前弹夹子弹余量就是弹夹最大容量了。

然后在前面的计算中,当判断TotalAmmo(总弹余量)小于当前所需子弹数量时,那么就说明不能上满弹夹了,所以只能有多少余弹就上多少了。所以我们通过CurrentAmmo加TotalAmmo得到当前弹夹中上弹后的子弹数量,然后设置给CurrentAmmo,然后再将TotalAmmo设置为0,即此时没有总弹余量了。

然后我们在Code目录下创建一个AnimNotify文件夹,然后在AnimNotify文件夹中创建一个蓝图类AN_Reload,继承自AnimNotify(动画通知)。

然后我们双击打开AN_Reload蓝图,在函数中点击重载已接收通知函数,然后通过已接收通知函数的MeshComp引脚创建一个获取拥有者节点,然后将获取拥有者节点的返回值转换为BP_WeaponBase蓝图对象,然后调用BP_WeaponBase蓝图对象的ReloadAmmo函数。

然后我们找到武器换弹动画蒙太奇,在这里面设置AN_Reload动画通知什么时候发送。

我们在武器换弹动画蒙太奇的动画轨道中找到弹夹插入枪械的那一帧,然后在通知轨道右键添加AF_Reload通知,然后将AF_Reload通知拖动到我们想要的时间线位置。

然后我们在BP_WeaponBase蓝图的EventTick事件后通过字符串附加节点来拼接出当前子弹和总弹余量数值,然后打印出来。

此时运行项目,开枪时可以看到当前弹夹余量减少了,换弹后总弹余量也减少了。

二、制作武器UI界面

1.制作武器UI界面

下面我们就来制作武器UI系统了,即在界面上显示武器类型和子弹数量等信息。

我们先将字体资源复制到项目根目录下的Content文件夹下面。

然后我们在Code目录下创建一个UI文件夹,然后在UI文件夹下面创建一个控件蓝图,命名为UI_MainUI。

然后我们双击打开UI_MainUI控件蓝图。

然后添加一个画布面板,然后添加一个图像控件到画布面板下面,重命名为WeaponIcon,然后设置图像控件WeaponIcon的锚点为右下角。然后设置图像控件WeaponIcon的图像为武器贴图。然后设置图像控件WeaponIcon的位置和大小。然后设置图像控件WeaponIcon的不透明度。

然后我们再添加两个文本控件到画布面板下面,分别命名为WeaponName和Ammo。WeaponName用来显示武器名称,Ammo用来显示武器弹夹子弹余量。然后先设置WeaponName和Ammo的锚点都是右下角。

然后设置Ammo文本的位置、大小、文本、字体和字形等。

然后设置WeaponName文本的位置、大小、文本、字体、字形和字体尺寸等。

然后我们选中Ammo文本控件,设置它为变量,因为Ammo文本控件显示的是武器当前弹夹余量和总弹余量,所以是需要根据开枪情况实时变化的。

然后我们在UI_MainUI控件蓝图的事件图表中,创建一个自定义事件UpdateWeaponInfo,在该事件后面执行武器信息的更新。然后我们通过Ammo变量创建一个设置文本节点,用来设置Ammo文本控件的显示文本。然后我们创建一个格式化文本节点,在Format中输入{Current}/{Total},然后可以看到格式化文本节点前面就出现了Current和Total引脚,这个节点可以将大括号中的内容转变为输入引脚,然后大括号外部的字符串正常显示出来。然后我们将格式化文本节点输出的文本结果传递给Ammo文本控件。

然后我们选中UpdateWeaponInfo事件,添加两个输入变量Current和Total,类型都是整数。

然后我们在BP_FPSPlayer蓝图的EventBeginPlay事件中通过创建控件蓝图对象节点创建一个UI_MainUI控件蓝图对象,然后将它提升为变量MainUI,然后再通过添加到视口节点将UI_MainUI控件蓝图对象添加到屏幕上显示。

此时运行项目,可以看到屏幕右下角就显示了武器图标和子弹信息。但是此时子弹信息是不会变化的。

我们在BP_WeaponBase蓝图的FireInternal事件后面通过Player变量获取到MainUI对象,然后通过MainUI对象调用UI_MainUI控件蓝图的UpdateWeaponInfo函数,然后将BP_WeaponBase中的CurrentAmmo变量和TotalAmmo变量的值传入到UI_MainUI控件蓝图的UpdateWeaponInfo函数的输入参数中,这样UI_MainUI控件蓝图中CurrentAmmo文本中显示的子弹信息就会实时更新了。

此时运行项目,开火时子弹信息会变化,但是换弹时子弹信息不变,这是因为我们没有在BP_WeaponBase蓝图的Reload事件后调用UI_MainUI控件蓝图的UpdateWeaponInfo函数更新子弹信息。

然后在AN_Reload动画通知中通过获取BP_WeaponBase对象来获取Player对象,然后获取Player对象的MainUI对象,然后调用MainUI对象的UpdateWeaponInfo函数,然后将BP_WeaponBase对象的CurrentAmmo变量值和TotalAmmo变量值传递给MainUI对象的UpdateWeaponInfo函数的输入参数。

然后在BP_VIRTUS蓝图中设置弹夹余量为30发。

此时运行项目,可以看到不管是开火还是换弹,子弹信息都更新了。

相关推荐
dong13269719 小时前
UE5FPS游戏开发教程(三)
ue5
日月云棠21 小时前
UE5源码分析之Editor——AnimationBlueprintLibrary模块全面分析
ue5
远离UE41 天前
UE5 ECS 原理
ue5
mengzhi啊3 天前
UE5 把剑绑定到骨骼-给要播放的动画及动画蒙太奇添加武器
ue5
directx3d_beginner3 天前
32,每帧更新怪物朝向改为c++
ue5
日月云棠3 天前
UE5源码分析之Editor——AnimationEditor模块全面分析
ue5
吴梓穆4 天前
UE5 播放透明视频
ue5
日月云棠4 天前
UE5源码分析之Editor——AnimationBlueprintEditor模块全面分析
ue5
远离UE44 天前
UE5 不同贴图采样类型的区别
ue5