存储系统SaveManager
存储系统SaveManager
背景
存储,几乎是所有游戏无法忽略的重要模块,使用什么样的方式保存数据,unity内置的PlayerPrefab,亦或是保存文件到本地,文件的形式是json还是xml,保存和读取数据的操作,序列化与反序列化数据。可见存储模块的多样性和复杂性。
框架引入EasySave插件来协助完成存储模块,再通过SaveManager对一系列操作进行封装,开发者通过SaveManager的api接口即可完成数据读取和保存。考虑到存储模块的复杂性和需求的多样性,框架将存储模块尽可能地独立存在,开发者可以 自定义存储模块 以满足具体需求,实现必要接口,即可无缝切换储存模块,无需对业务逻辑进行任何修改。
插件官方文档
(文末有存储系统SaveManager 具体使用和拓展 的案例)
使用
数据文件路径
- 通过unity界面上方“存档目录”摁钮,定位到游戏的数据目录,即 数据文件fileName 或 数据文件路径filePath 的 根目录。
- fileName 即 文件名,根目录为存档目录,文件名fileName 等价于 文件路径filePath。
API接口
自定义实现存储模块时必须实现的SaveManager接口,即可实现 无缝切换 存储模块。
1 | public class SaveManager : BaseSingleTon<SaveManager> |
API使用示例
以保存和读取当前存档的背包数据举例:
1 | // 保存所有背包数据到当前存档的存档文件 |
背包数据结构:
1 | // <背包名,背包数据> |
注意事项
- 虽然EasySave会自动进行序列化,但是开发者仍然需要保存的数据结构需要显式声明[Serializable],避免说如果更换了存储模块,自定义的存储模块不一定会自动进行序列化操作,导致数据保存失败。
- 本文与资源管理系统的模块定位需要区分,资源管理系统保存的资源和数据是不会进行变更的,只能进行加载操作,而本文指的数据是在游戏运行中动态进行读取的,甚至是文件删除和创建的动态操作。
- EasySave插件可以实现加密功能,开发中使用 明文以及json格式 保存,是为了方便查看和验证文件中的数据。
- 自行实现加密格式,可以借助框架封装的,工具类Utils中的,常用加密解密 部分。
1
2
3
4
5
6
7// 工具类路径:项目路径\Assets\Scripts\Misc\Util\UtilsForEncode.cs
// 使用示例:
// AES加密字节流,Utils.AesEncrypt(字节流,秘钥)
var content = File.ReadAllBytes(fileName);
var encryptContent = Utils.AesEncrypt(content, "yufulao@qq.com");
// AES解密字节流,Utils.AesDecrypt(加密字节流,秘钥)
var decryptContent = Utils.AesDecrypt(encryptContent, "yufulao@qq.com");
夹带私货(存档功能)
项目当前的数据存取流程:
初步设置了基础的数据类别,包括全局数据Global、配置数据Cfg、存档数据。Cfg设置数据文件 和 Global全局数据文件 是主要文件MainFile,会在游戏启动时进行创建和初始化,SaveGame存档数据文件则需要手动创建和初始化。
- 数据目录:
- 存档数据目录SaveGame:
- 存档数据的必要数据结构:
1
2
3
4
5// 项目路径\Assets\Scripts\Core\Manager\SaveManager\SaveGameStruct.cs
public struct SaveGameStruct
{
public string SaveGameTitle; // 存档标题
} - 存储的方式
1
2
3
4
5
6
7// 项目路径\Assets\Scripts\Core\Manager\SaveManager\SaveType.cs
public enum SaveType
{
Cfg, // 保存到设置文件
Global, // 保存到全局文件
SaveGame, // 保存到当前存档文件
} - 新增API
1
2
3
4
5
6
7
8
9
10
11
12
13// 设置当前存档index,可以在 进行存档选择时 进行调用,无存档功能的指定唯一存档文件名即可
public static void SetCurrentSaveGame(int saveGameIndex)
// 重置 所有文件,(删除Cfg、Global、所有存档文件。再新建Cfg和Global文件)
public static void ResetAllFile()
// 删除 所有存档文件
public static void DeleteAllSaveGame()
// 获取 当前存档index 对应的 存档文件名
public static string GetSaveGameFileName(int saveGameIndex)
// 以保存数据方式saveType,更新或创建 k,v 数据项
public static void Set<T>(string k, T v, SaveType saveType)
// 获取数据项,需要给出默认值,没有键时创建默认数据项,以saveType读取对应文件
public static T Get<T>(string key, T defaultValue, SaveType saveType)
评论