You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测BinaryFormatter序列化完成时机 避免游戏存档异常

解决BinaryFormatter存档写入未完成即退出导致的存档损坏问题

BinaryFormatter.Serialize() 本身是同步阻塞方法,只要这行代码执行返回,对象序列化的内存操作就已经全部完成,不存在序列化逻辑跑一半的情况。你遇到的存档失效问题本质是文件流缓冲区数据未强制落地、资源释放逻辑不完善导致的:

  • 调用Stream.Close()时,仅能保证.NET运行时层面的流缓冲区数据提交给操作系统,不会强制等待操作系统把缓存写入物理磁盘,此时立刻终止进程会导致文件只写入了部分内容
  • 没有用托管逻辑释放流资源,一旦序列化过程中触发异常,文件流会被直接中断,留下损坏的半写存档文件
  • 如果你的代码逻辑是调用存档方法后立刻执行退出,没有等待整个IO流程走完,也会加剧这个问题

修正后的可安全退出的存档实现

void ExecuteSaveAndQuit()
{
    BinaryFormatter formatter = new BinaryFormatter();
    // 用Path.Combine拼接路径,自动适配不同操作系统的路径分隔符
    string savePath = Path.Combine(Application.persistentDataPath, "Gmaster.fun");
    PlayerData saveData = new PlayerData();

    // using块会在代码段执行结束后自动释放文件流资源,哪怕中途抛出异常也不会残留文件锁
    using (FileStream writeStream = new FileStream(savePath, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        formatter.Serialize(writeStream, saveData);
        // 关键:强制将所有层级的缓冲区(包括操作系统层面的文件缓存)写入物理磁盘
        writeStream.Flush(flushToDisk: true);
    }

    // 代码执行到此处时,存档已经100%写入磁盘完成,可以安全触发退出
    Application.Quit();
}

落地注意事项

  • 不要把完整存档逻辑绑定到OnApplicationQuit这类生命周期回调上,移动端、主机端系统给应用退出的预留时间通常只有1-2秒,大体积存档很容易写不完就被系统强杀。“保存并退出”按钮的逻辑要走主动触发:点击按钮后先弹出不可交互的保存中提示,等上述存档方法完全执行完毕再自动退出
  • 可以加一层简单的存档校验:写完文件后可以立刻读一遍文件头,确认文件长度符合预期再走退出逻辑,进一步降低坏档概率
  • 稳妥起见可以加备份机制:写入新存档前先把旧存档重命名为备份文件,新存档写入校验通过后再删除备份,就算遇到断电、强退等极端情况,下次启动也能读备份恢复
  • 额外提一句:BinaryFormatter存在已知的序列化安全漏洞,如果后续要做MOD支持、联网同步存档这类功能,建议替换为JsonUtility、MessagePack等更安全的序列化方案,纯本地单机存档使用没有问题

内容的提问来源于stack exchange,提问作者tok23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:09:22