野外生存游戏【1. 库存系统】
野外生存游戏【1. 库存系统】
鲸拓工作室UE版本:5.2.1
本章实现效果预览
注:本文是为多人游戏设计的,所以在某些部分会比较繁琐,可根据个人需求自行调整。另外,获取到项目工程文件之后,需做此设置才能正常运行
系统框架
基于第一人称游戏创建项目
项目文件结构如下
- _Main文件夹用于存放所有开发文件
- Blueprints用于存放蓝图
- DataTables用于存放数据表
- Enums用于存放枚举
- GameModes用于存放游戏模式
- Interfaces用于存放接口文件
- Inventory用于存放库存系统相关蓝图
- Items用于存放物品
- Structures用于存放结构体
- Widgets用于存放视图组件
- InventoryWidgets用于存放库存相关的视图文件
- Textures用于存放纹理资源文件
- Blueprints用于存放蓝图
物品存放
UI
先来创建UI界面,实现效果如下
需要创建的 Widgets 有这些(另外两个用于实现拖放逻辑)
UI 逻辑如下(这里没有详细截图,只是放个大概,可以自行查看项目文件或者根据喜好自行调整)
物品定义
首先创建如下枚举,用于定义物品的类型、属性、稀有度等信息
接着创建一个结构体,用于定义物品
其中 BP_ItemMaster 是一个基类,先直接定义在 Item 文件夹下即可,暂时用不到
定义好之后再创建一个数据表,新增一个木头物品
到这里,物品相关的定义就完成了,接下来开始编写逻辑实现物品添加
新增物品
期望效果是按下1键,游戏就能从数据表中读取第一条物品并添加到库存中。
实现逻辑是:当用户按下1的时候,先读取物品信息,然后找到库存中为空的索引,将它存到一个固定长度的items数组里,接着更新UI即可
先创建一个自己的 GameMode 和 PlayerController
然后在 Inventory 文件夹下创建这两个 ActorComponent,其中 BPC_PlayerInventory 继承自 BPC_ItemsContainer
打开 BPC_ItemsContainer ,创建一个自定义事件,用于新增物品
函数的具体实现逻辑如下,先找到一个空的槽位,然后更新UI
Find Empty Slot 实现逻辑如下,遍历 Items,通过 ItemID 是否为0来判断槽位是否为空
Update UI 的实现逻辑如下,通过接口找到 Player Controller 的引用,然后通过 Player Controller 去调用 widget 来更新 UI(这里之所以要用接口传来传去搞得这么复杂,是为了要在多人游戏中区分客户端,可以根据自己的需求适当简化)
其中用到的接口为 BPI_SurvivalCharacter
再创建一个 BPI_SurvivalGamePC 接口,挂在 Player Controller 上,就基本打通了获取引用这个过程
继续在 PlayerController 里面编写逻辑,前文说了要通过 PlayerController 来控制 Widget,所以这里先在开始运行的时候获取到 Widget 的引用
接着在这里面创建两个事件,用于调用 Widget 来更新和重置槽位
具体 Widget 里面的实现逻辑如下
最后把 BPC_PlayerInventory 挂载到 BP_FirstPersonCharacter 上就好了
OK,那么到这里,整个逻辑就打通了。运行游戏,按下Tab键会显示库存界面,按1就会新增物品
拖拽物品
这里想做到的是,打开库存栏之后,我们拖拽物品可以移动到不同的槽位
实现逻辑如下:
1、点击物品,记录下当前选中的槽位索引和物品信息
2、拖拽物品,创建一个可拖拽的widget,并将信息复制上去
3、放在物品,找到鼠标落点处的槽位索引,将信息放进去,然后删除之前槽位的数据
首先打开 W_InventorySlot,重载这三个函数,分别对应了上面提到的三步
下面这个函数就检测了拖拽这个操作,W_InventorySlot 本身的 ItemInfo 变量就记录了物品信息,随后创建可拖拽的actor和对应的widget
分别是这两个
继续重载Drop函数,表示已经拖到位置,准备放下了
其中 BP_FirstPersonCharacter 里面的 OnSlotDropOnServer 函数逻辑如下
它调用了 BPC_PlayerInventory 里面的函数,但是 BPC_PlayerInventory 又是继承自 BPC_ItemsContainer 的,所以我们先打开 BPC_ItemsContainer, 编写 OnslotDrop 函数
但是它的 Handle Slot Drop 函数是空的,因为要留在 BPC_PlayerInventory 里面实现
所以我们回到 BPC_PlayerInventory ,重载 Handle Slot Drop 函数
这个函数找到了初始的 container, 并调用了核心的 transferItem函数
其中 Add Item to Index 等子函数逻辑如下
注意还有 Remove Item at Index 也被 BPC_PlayerInventory 重载了
OK,到此为止,拖拽的逻辑就基本完成了