存档系统设计(D8:存档接入)
对应开发计划表 D8(8/10):① SaveSystem JSON 序列化 ② 存/读接口 ③ 替换 SavePanel 测试数据。
交付标准:读档后数据还原。本文档只描述设计,不包含代码。
状态:全部步骤已实现(SaveSystem/序列化/GameState+MainGame 分支/SavePanel 双模式/自动存档/两级浏览/读档还原/删除与容错/游戏内加载进度点/删除存档组),验收 1–9 全部通过
一、两级存档结构(无限组 / 无限槽)
第一级:存档组 SaveGroup(一个角色/一次轮回,UI 显示"存档N") → 第二级:存档槽 SaveSlot(该组下任意多个进度快照)
- 每个新游戏 → 创建一个 SaveGroup(主菜单"新游戏"时自动生成,id 自增)
- 每次点击存档 → 在所属 SaveGroup 下创建一个新 SaveSlot(不覆盖、不固定槽位)
- 组和槽的数量均无上限
- 槽位命名:组内序号递增(
slot_1、slot_2…),同一组内永不重名、互不覆盖;删除槽位后序号从当前最大 +1 继续(不重用)
- 自动槽
auto.json 固定名(续档用)
二、可存档数据清单
| 系统 |
数据 |
说明 |
| GameState |
year/month/day |
游戏日期(TimeSystem.set_date 恢复) |
| SectManager |
spirit_stones / reputation / food |
三资源 |
| DiscipleManager |
disciples + _next_id |
名录;候选池不存 |
| BuildingManager |
buildings |
建筑类型/等级 |
修为/境界/饥饿天数都在 Disciple 字段内,随名录序列化。
三、SaveSystem(新 Autoload)
存放位置:src/Core/SaveSystem.gd,注册于 project.godot(依赖各管理器,声明在最后)。
| 接口 |
说明 |
create_profile() -> int |
新建存档组,返回 id(名"存档N") |
get_profiles() -> Array[Dictionary] |
存档组列表(id/name/created/last_date) |
save_game(profile_id) -> String |
新建一个槽位并写入当前游戏数据,返回槽文件名;失败返回空串 |
save_auto(profile_id) -> bool |
写自动槽(返回主菜单时调用) |
get_slots(profile_id) -> Array[Dictionary] |
该组全部槽位(槽文件名 + 元数据),按时间升序 |
load_game(profile_id, slot_name) -> bool |
读取槽位 JSON → 还原各系统 |
delete_profile(profile_id) -> bool |
删除存档组(列表移除 + 递归删目录含全部槽位) |
delete_slot(profile_id, slot_name) -> bool |
删除槽位文件 |
reset() |
清空内存游戏数据(各管理器 reset + 资源清零) |
四、序列化设计
1. 数据模型加 to_dict/from_dict
Disciple.to_dict() / static Disciple.from_dict(data)(14 字段全量,枚举转 int)
Building.to_dict() / static from_dict(data)(2 字段)
2. 槽位 JSON 结构(slot_1754734800.json)
saved_date/resources 顶层冗余字段 = 槽位元数据(列表显示用,免解析全档)
version 为格式版本,预留兼容
3. profiles.json 结构
五、存档/读档流程
存档(游戏内,每次=新建槽)
- TopBar 新增"存档"按钮 → SavePanel(存档模式,时间暂停)
- 左侧显示存档组(当前组高亮),右侧显示该组全部槽位
- 点"新建存档"按钮 →
save_game(profile_id) 创建新槽 → 列表新增一条
- 关闭面板恢复时间
读档(主菜单,两级浏览)
- 主菜单"读取存档" → SavePanel(读档模式)
- 左侧存档组列表(存档N + 最后日期)→ 点组 → 右侧显示该组槽位列表(自动+手动,元数据齐全)
- 点槽位 →
GameState.request_load_game(profile_id, slot_name) → 进入 MainGame
MainGame 分支(改造 _ready)
自动存档
TopBar"返回"主菜单时(sign_return_mainmenu 处理前)→ save_auto(profile_id) 自动槽——保证"退→再进"能续档。
六、UI:SavePanel(复用现有手绘界面)
SaveSlot 条目(复用现有场景,无空槽概念——每个条目都是真实存档):
| 节点 |
填充内容 |
| SlotIndexLabel |
序号(自动槽=0,手动槽按时间序 1..N) |
| SaveNameLabel |
"自动存档" / "存档 N" |
| MetaLine1 |
"X年X月X日 弟子N人" |
| MetaLine2 |
"灵石 M" |
| DeleteButton |
删除该槽位(删除前确认) |
| ArrowIcon |
读档箭头(点击读档) |
交互规则:
| 项 |
存档模式(游戏内) |
读档模式(主菜单) |
| 左侧组列表 |
当前组高亮(可切换查看,组行带"删"按钮,当前组禁用) |
可切换任意组(组行带"删"按钮) |
| 槽位点击 |
回到该进度点(加载所选槽,未保存进度丢失) |
点击读档进入游戏 |
| 删除按钮 |
可删(确认后) |
可删(确认后) |
| 暂停 |
打开时暂停,关闭恢复 |
不暂停 |
七、分步实现规划(小步可验证,每步独立跑通)
步骤 1:SaveSystem 骨架(新 Autoload)✅
| 项 |
内容 |
| 改动 |
新建 src/Core/SaveSystem.gd:create_profile()(建组,名"存档N")、get_profiles()、save_game(profile_id)(新建槽,文件名 slot_{组内序号}.json,返回槽名)、save_auto(profile_id)、get_slots(profile_id)(自动槽最前+手动按序号升序,含元数据)、load_game(profile_id, slot_name)、delete_slot()、reset();project.godot 注册(声明在最后) |
| 验证 |
✅ 建组(存档N 自增)→ 存档 → slot_1/2/3 生成 → get_slots 读回;删除后序号不重用 |
步骤 2:数据模型序列化 ✅
| 项 |
内容 |
| 改动 |
Disciple.to_dict()/static from_dict()(14 字段,枚举转 int);Building.to_dict()/static from_dict();DiscipleManager 加 get/set_next_disciple_id();SectManager 加 set_spirit_stones/set_reputation/set_food()(带信号,读档后 HUD 自动刷新) |
| 验证 |
✅ 存档文件内容完整(弟子/建筑/资源/日期全量) |
步骤 3:GameState + MainGame 分支 🟡(GameState 已改,MainGame 分支待接)
| 项 |
内容 |
| 改动 |
GameState 加 profile_id: int、save_slot: String(槽文件名);request_new_game(pid)、request_load_game(pid, slot_name);MainGame._ready 分支 NEW_GAME(原流程)/ LOAD_GAME(load_game 还原,不弹窗不暂停,失败回退新游戏);sign_return_mainmenu 前 save_auto(profile_id) |
| 验证 |
无头:存→清→读闭环,日期/资源/名录(境界修为饥饿)/建筑逐项一致 |
步骤 4:SavePanel 动态填充(复用现有手绘界面)✅
| 项 |
内容 |
| 改动 |
SavePanel.gd 双模式:存档模式(游戏内,暂停,当前组高亮 + 槽位列表 + "新建存档"按钮 → save_game → 列表新增);读档模式(主菜单,左列组列表 → 点组 → 右列槽位列表,点槽读档)。SaveSlot.gd 填充:序号/名称/MetaLine1/MetaLine2/删除(确认后删)/箭头(读档)。TopBar 加"存档"按钮 + sign_open_save 信号 |
| 验证 |
✅ 存档模式:打开暂停 → 新建存档 → 槽位生成(内容完整)→ 关闭恢复;读档模式待 F5 手测 |
步骤 5:接线闭环 🟡(MainMenu 建组已接,读档模式接线+自动存档待做)
| 项 |
内容 |
| 改动 |
MainMenu"新游戏"→ create_profile() 建组 → 进游戏;"读取存档"→ 面板读档模式;MainGame.tscn 挂 SavePanel 实例 |
| 验证 |
完整闭环:新游戏(建组)→ 招弟子 → 挂机 → 存档(建槽)→ 返回(自动槽)→ 主菜单读档 → 数据还原 |
步骤 6:整体验证 + 提交
| 项 |
内容 |
| 改动 |
无(仅验证) |
| 验证 |
对照八节验收清单逐项勾选;git 提交 |
依赖关系:1→2 顺序执行(序列化被 SaveSystem 消费);3 依赖 1/2;4 依赖 1/3;5 依赖 4;6 为最终验证。
八、验收清单(D8 交付标准)