引言
单机游戏数据的自动保存方案
大家好,2023年还有最后的3天!
有小伙伴私信我,说:
总感觉一股脑的全盘定时保存不科学,也写过保存变化的玩家数据,但是改完数据就得手动标记一下字段变化,感觉不够智能,不知道有没好的设计模式之类可以解决,就只管更新数据就行。
笔者认真思考了一下,结合前面的项目里面用到的,给大家分析一下,大家可以根据具体情况看看。
本文将介绍一下单机游戏数据的自动保存方案。
本文源工程可在文末阅读原文获取,小伙伴们自行前往。
1.需求分析
根据小伙伴的私信,需求如下:
- 全盘定时保存不科学。
- 保存变化的玩家数据,需要手动标记,不智能。
- 有没有办法只管更新数据就行。
我们接下来具体分析一下
2.具体分析
1.全盘定时保存
其实全盘定时保存也不是不好的设计方案,只是他也是需要针对变化的数据进行存盘。
也就是说我们需要对变化的数据进行标记,在执行全盘保存的时候,需要根据标记位来进行存储。
这方案在后端开发其实是很常见的,定时存盘+离线存盘。
能够有效地保证数据存储无误、存储效率更高,服务器宕机时损失最少。
2.手动标记
手动标记其实是最有效,最直接的去控制指定内容是否需要存盘的方法。
但是由于是手动标记,也就是人为操作,难免会出现错漏的情况。
因此可以借助一下设计模式,去优化一下设计,在数据变化时可以自动标记。
下面一起来看下自动保存常用设计模式
3.数据自动保存设计模式
下面是查阅相关资料之后整理出来的一些设计模式和方法:
-
观察者模式: 使用观察者模式来监测游戏中的变化。每个可能修改数据的对象都是观察者,而存档系统是主题。当对象发生变化时,它通知主题,主题再负责触发保存。
-
Dirty Flag模式: 引入“脏标志”来标记对象是否发生变化。只有在对象发生变化时才进行保存。这种方式可以减少不必要的保存操作。
-
快照模式: 定期创建游戏状态的快照,而不是全盘保存。这样可以避免频繁的保存操作,只在需要时加载最近的快照。
-
增量保存: 只保存发生变化的部分数据,而不是整个数据集。这可以减少保存和加载的时间,尤其是在数据量较大的情况下。
接下来直接看下实例
4.观察者模式
我们使用观察者模式来完成一个数据自动保存的实例。
首先我们准备一下玩家数据,其中包括:
- 角色名
- 等级
// PlayerData.ts
export class PlayerData {
name: string;
level: number;
constructor(data: any) {
this.name = data.name;
this.level = data.level;
}
}
然后,我们定义一个通用的观察者接口:
// Observer.ts
export interface Observer<T> {
update(data: T): void;
}
再然后,实现一个具体的观察者,即自动保存数据的观察者,核心内容如下:
save
负责存储数据,这里可以根据具体需求存本地或者服务器。load
负责数据加载。
import {
sys } from "cc";
import {
Observer } from "./Observer";