◆ 持续开发中 · 当前为非稳定版本,如需抢先体验请通过 GitHub Issues 联系作者

存档存储 Save

把一个可序列化对象按类型写盘、按类型读回。就这一件事。

命名空间 HYC.Framework.Save。已实现,依赖 com.unity.nuget.newtonsoft-json(已在框架 package.json 声明)。

用法

using HYC.Framework.Save;

[Serializable]
public class PlayerProgress
{
    public int level;
    public int coins;
    public Dictionary<string, int> levelStars;   // Dictionary 只有 Newtonsoft 支持
}

// 存
SaveManager.Save(new PlayerProgress { level = 3, coins = 120 });

// 取:不存在时返回 null
var p = SaveManager.Get<PlayerProgress>();

// 取:不存在时新建一个(不自动写盘,什么时候落盘仍由调用方决定)
var p2 = SaveManager.GetOrCreate<PlayerProgress>();

// 判断 / 删除
bool has = SaveManager.Has<PlayerProgress>();
SaveManager.Delete<PlayerProgress>();
SaveManager.DeleteAll();

自定义序列化器与根目录:

SaveManager.Init(new SaveOptions
{
    Serializer = new JsonUtilitySaveSerializer(),
    RootPath   = Path.Combine(Application.temporaryCachePath, "SaveTest")
});

核心类

类职责
SaveManager静态入口
SaveOptionsRootPath(默认 persistentDataPath/Save,可覆盖便于测试)、Serializer
SaveEnvelope文件外壳,带 formatVersion / typeKey / timestamp / payload
ISaveSerializer序列化抽象
NewtonsoftSaveSerializer默认实现,支持 Dictionary / 多态 / 顶层 List<T>
JsonUtilitySaveSerializer零依赖备选,有三条硬限制

坑

  • Get<T>() 每次都读盘,没有内存缓存。别放在每帧循环里。这是设计取舍:不缓存就没有生命周期、没有失效问题、没有 Clear()。
  • 坏档会被改名成 .corrupt_<时间戳>,不会被覆盖。静默覆盖等于玩家进度凭空消失且无从追查。
  • 类型就是键:文件名键是 typeof(T).FullName,给类改名或换命名空间 = 老存档读不到。真要改名时写一次性迁移代码,框架不做这个。
  • 同一个类型只能存一份。想存多份就存 List<T>。
  • JsonUtilitySaveSerializer 三条硬限制:不支持 Dictionary、不支持多态、顶层不能直接是 List<T>。用之前先确认数据不触碰这三条,否则会静默存出 {}。
  • 自动保存时机不由框架决定:使用方需自己在 OnApplicationPause / OnApplicationFocus(false) 里调 Save。