学习空间/存档坏了怎么办:验证、备份与版本恢复练习
上手工作坊 / LESSON 57

存档坏了怎么办:验证、备份与版本恢复练习

把成功读档、损坏拒绝和旧版本迁移一起设计,而不是只验证写出一个文件。

进阶实作约 8 分钟阅读,实作另计6 节按需学
CONCEPT MAP先看一眼知识之间的联系
先看一眼知识之间的联系01读取候选02解析与校验03必要时迁移04再次校验05应用 / 验证备份
在临时数据中完成验证,再一次性改变游戏状态。

01前置:把测试存档和真实进度彻底分开

使用独立练习项目和专用 user:// 文件名,不读取或修改正式游戏存档。先完成基础课程中的一次写入与读回,再进入本课。目标不是制造“永不损坏”的承诺,而是在坏文件、旧版本和写入失败面前,尽可能保留最近可用进度,并且把真实情况告诉玩家。

先列出最小数据:schema_version 表示格式版本,room_id 用稳定字符串标识房间,flags 保存事实。不要保存节点实例、场景树路径猜测或任意对象。格式版本与游戏发行版本是两回事:美术更新可能不改格式,字段含义改变则可能需要迁移。

02第一步:先定义有效,再谈读取成功

给练习格式写一份小约定:顶层必须是字典;版本必须是可识别的整数值;房间只允许练习已知的标识;flags 必须是字典,关键旗标必须是布尔值。字段缺失是否可补默认值,要逐项决定,不能用一堆默认值把损坏伪装成新游戏。

下面只演示 JSON 解析层,不是完整存档系统。给 Node 挂脚本并在自己的读取函数中调用它;关键 API 已按 Godot 4.7 文档核对,未完成实际场景交互验证。解析成功后还要继续做字段、范围和版本检查。

extends Node

func parse_object(text: String) -> Dictionary:
    var parser: JSON = JSON.new()
    var error: Error = parser.parse(text)
    if error != OK:
        return {"ok": false, "reason": parser.get_error_message()}
    if not parser.data is Dictionary:
        return {"ok": false, "reason": "顶层必须是字典"}
    return {"ok": true, "data": parser.data}

03第二步:只把完整验证后的数据应用到游戏

读档顺序采用“读文件 → 解析 → 校验 → 迁移 → 再校验 → 应用”。先在临时数据里完成全部步骤,不要读到一个字段就立即移动玩家,再读到下一个字段才发现版本不兼容。数值经过 JSON 往返后不能假设仍保留原始整数类型,应验证其数值确为整数并在范围内,再转换。

对于版本高于当前程序的存档,明确提示需要较新游戏版本,保留原文件,不自动降级或覆盖。当前文件失效时,再验证备份;备份有效才能提供恢复选择。两份都无效时,提供新开游戏和定位诊断文件的方式,不无限循环弹窗,也不悄悄吞掉玩家进度。

04第三步:把写入设计成有失败出口的流程

保存时先形成一个完整状态快照,写到同目录临时文件,检查打开和写入结果,刷新缓冲并关闭,再重新读取验证。验证通过后,保留最近已验证的旧存档作为备份,再按平台策略替换当前文件。每一步失败都停止后续覆盖,界面显示“保存失败,上一份可用存档已保留”,而不是提前弹出保存成功。

临时文件加 rename 是降低风险的策略,不等于跨平台、断电情况下的强原子保证。 删除旧文件再重命名还会产生空档窗口;文件系统、替换接口、缓冲落盘和异常退出都影响结果。不能只看到一次 rename 返回成功,就宣称永不丢档。正式接入前需针对目标 Windows 环境验证失败路径。

05第四步:用小迁移练习学习兼容,而不篡改原件

设练习 v1 使用 has_token,v2 改为 flags.token_taken。迁移函数输入旧字典,输出新的 v2 字典;原文件保留不动。先验证 v1 的字段是真假值,再转换,最后用 v2 规则检查。不要直接在损坏数据上硬塞 version = 2,当作完成迁移。

为每个旧格式保存一份匿名测试样本,并记住成功迁移后的预期。迁移链按 v1 到 v2、v2 到 v3 分步组织;当前只实现真实需要的一步,不预建十个未来版本。遇到未知房间标识时,只有明确设计过安全回退点才允许回退,否则应拒绝并说明,而不是把玩家丢到不存在的场景。

06故障注入与验收:让坏事发生在练习副本里

复制五份测试文件,分别制作空文件、截断 JSON、把布尔改成文字、旧版本、未来版本;另测主档坏而备份好的组合。对每份写出预期:拒绝原因、是否允许恢复、原文件是否仍存在。用测试开关模拟写入返回错误,比把正式磁盘塞满更可控。

验收还包括成功保存后关闭并重启、连续保存两次、取消恢复、不兼容版本不会被自动覆盖。校验和能帮助发现部分非预期字节变化,但不是备份,更不是防作弊证明。练习的完成标准是“正常路径能读回,失败路径不误报成功,恢复有可解释结果”,而非代码里出现了几个文件 API。

动手后,再勾选

不是“我看懂了”,而是你在独立练习里做出并检查过。

CHECK YOUR UNDERSTANDING

换一个情景,你会怎么判断?

JSON 能成功解析,是否就可以立刻把它应用为玩家进度?

用自己的话,留一条笔记

可以写“我之前以为……,现在发现……”,或者记录还没解决的问题。

仅保存在此浏览器0 / 20000

回到资料核对

本课是解释与练习,不替代对应版本的官方手册。网页实验不运行 Godot;未标明实机验证的代码,仍需在独立工程中检查。

把这课收进你的理解里。

标记已读不会自动勾选实作,也不代表游戏功能已经完成。

输入一个你想弄明白的问题。

按 Esc 关闭 · 标题、关键词和正文一起搜索