开发者日志#4:工欲善其事——存档系统
10/2412 浏览综合
大家好,这里是黄昏喵喵工作室!
在上一篇日志中,我们介绍了功能强大的状态机组件(State Machine),用来管理各种角色、物件甚至流程的状态转换。
这样一来,我们就能够轻松配置出更加复杂的游戏关卡,但同时也带来了一个问题:我们该如何准确地记录这些状态,比如任务进行到哪一步了,物品有没有被拾取?
所以,我们今天就来了解一下游戏世界的存档系统(Save Game)。
存什么?
不同类型的游戏对存档功能复杂程度的要求可能会存在差异,但至少都要实现最基础的功能:记录关键信息(比如游戏进度、玩家数值等),然后在需要的时候能够读取并还原。
UE中提供了USaveGame作为一个存档结构的基类,开发者可以在自定义的子类中按照游戏设计增加成员变量。在保存时,游戏存档通常以 .sav 文件的形式存储在特定的目录中,允许同时存在多个文件。
在触发存档时,我们会通过消息系统向世界广播一个事件,需要保存信息的物件收到消息后,向存档结构中写入数据,然后再将存档保存到硬盘上,这样就实现了存档机制。
怎么存?
游戏的一条存档信息本质上可以看作一个被序列化的记录文本,存、读、判空等行为则通过GameplayStatics提供的标准函数实现,开发者可以在功能层面进一步封装实现存档记录的增删改查(数开人的DNA动了)。
- 保存数据到插槽 :UGameplayStatics::SaveGameToSlot(SaveGameInstance, TEXT("SlotName"), 0);
- 加载存档 :UMySaveGame* LoadedGame = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(TEXT("SlotName"), 0));
- 检查存档是否存在:bool bExists = UGameplayStatics::DoesSaveGameExist(TEXT("SlotName"), 0);
进展
目前我们已经完成了存档模块的代码实现,并和UI的按钮事件进行了绑定。
另外,虽然目前我们的关卡还没有搭建好,但已经先行测试了游戏流程的触发和存读档。至今为止,我们已经将程序上搭建好的基础模块串联到一起,实现了一个非常通用的链路:
- 事件触发 ——> 广播事件(通过Message System) ——> 状态更新 (State Machine) ——> 自动存档(Save Game)
下期预告
至此,《工欲善其事》系列的技术分享就结束了。接下来,我们会展开具体关卡的搭建,游戏的画面表现和游玩体验也会逐渐丰满起来。下一篇,我们将分享在游戏主角的设计和测试过程中的碎碎念,敬请期待!


