关于 save-load
面向 Godot 4.3 及以上版本开发者的存档与读档技能,比较序列化方案,并介绍设置、游戏存档、保存架构、存储位置和版本迁移,提供 GDScript 与 C# 示例。
主要功能
- 01比较 ConfigFile、JSON 和 Resource
- 02设置与游戏存档序列化指南
- 03SaveableComponent 保存架构模式
- 04存档路径与版本迁移
- 05Resource 文件安全注意事项
适用场景
- 01保存音频、视频或控制设置
- 02将游戏状态保存为可读文件
- 03整理跨游戏节点的持久化状态
- 04随数据结构变化迁移旧存档
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill save-load安装后在 Claude Code 中输入/save-load确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/configfile.mdjson-saves.mdsave-architecture.mdversion-migration.md详细介绍
Godot 4.3+ 中的保存 / 加载系统
根据数据类型选择合适的序列化策略。所有示例均面向 Godot 4.3+,不使用已弃用的 API。
相关技能: 自定义 Resource 数据容器使用 resource-pattern,物品栏序列化模式使用 inventory-system,SaveManager 自动加载设置使用 godot-project-setup,冒险框架存档使用 popochiu。
1. 策略对比
| 策略 | 最适合 | 可读 | 编辑器支持 | 备注 |
|---|---|---|---|---|
| ConfigFile | 设置、简单的键值数据 | 是 | 否 | 内置 INI 风格,无需额外依赖 |
| JSON | 游戏存档、灵活的数据结构 | 是 | 否 | 跨平台,可迁移版本 |
| Resource .tres | 与编辑器集成的数据 | 是 | 是 | 不安全——切勿加载不可信文件 |
| Resource .res | 快速二进制数据 | 否 | 是 | 不安全——切勿加载不可信文件 |
推荐策略时,请说明你排除的方案,以及决定性因素——“选 JSON 而不是 Resource 文件,因为存档可由用户写入,而加载 Resource 可能会运行代码”。如果没有明确指出替代方案,就无法推翻所选格式。
安全警告: 加载
.tres或.res文件会执行嵌入资源中的任意 GDScript。切勿加载来自不可信来源(用户上传的文件、下载的模组)的 Resource 文件。用户生成的存档数据请使用 ConfigFile 或 JSON。
2. ConfigFile——设置
ConfigFile 会写入 INI 风格的分区,非常适合音频 / 视频 / 控制设置(数据量小,方便设计人员调试)。使用 set_value(section, key, value),然后调用 save(path);使用 load(path) 加载,再通过 get_value(section, key, default) 读取。
完整的 GDScript + C# 设置保存 / 加载示例,以及常见的设置菜单接线方式,请参阅 references/configfile.md。
3. JSON——游戏存档
使用 JSON.stringify(dict) 序列化,使用 JSON.parse_string(text) 反序列化。通过 FileAccess 读写。适用于需要可读文件的游戏存档。构建一个包含所有游戏状态的 Dictionary(玩家位置、物品栏、世界标记),进行序列化,然后写入 user://save_<slot>.json。
完整的 GDScript + C# 保存 / 加载实现(包括 FileAccess 封装和错误处理),请参阅 references/json-saves.md。
⚠️ Godot 4.7 中的变更: 即使传入了
indent,JSON.stringify(data, indent = "", sort_keys = true, full_precision = false)现在也会将空Dictionary紧凑地序列化为{}(GH-115883)。升级后,带缩进写入的存档文件中,空字典字段的格式会发生变化;任何逐字节比较或计算存档输出哈希的操作都必须兼容这种新格式。解析不受影响。
4. 存档架构模式
对于大型游戏,可在每个需要持久化的节点上挂载一个 SaveableComponent。每个组件都持有稳定的 save_id 和两个可调用对象 serialize、deserialize,并加入 saveable 组。存档管理器会遍历该组,调用每个组件的 serialize,并构建一个以 save_id 为键的主 Dictionary。
完整的
SaveableComponent+ 存档管理器实现,请参阅 references/save-architecture.md。
5. 存档文件位置
user:// 会解析为项目文件夹之外的平台专属可写目录。
| 平台 | 路径 |
|---|---|
| Windows | %APPDATA%\Godot\app_userdata\<project-name>\ |
| macOS | ~/Library/Application Support/Godot/app_userdata/<project-name>/ |
| Linux | ~/.local/share/godot/app_userdata/<project-name>/ |
存档数据始终使用
user://,切勿使用res://。在导出的构建中,res://路径为只读。
6. 版本迁移
存档文件的生命周期可能超出其写入时所用架构的生命周期。始终在已保存的 Dictionary 顶部包含 "version": <int>;加载时根据版本进行分支,并逐步将旧存档迁移到新版本(v1 → v2 → v3 → current)。切勿破坏旧存档——始终进行迁移。
完整的迁移辅助函数模式请参阅 references/version-migration.md。
7. 实现检查清单
- 设置使用 ConfigFile,游戏存档使用 JSON(而非 Resources)
- 每个存档文件都包含
version整数字段 - 存档路径使用
user://,切勿使用res:// - 写入存档前调用
DirAccess.make_dir_recursive_absolute() - Vector2/Vector3 序列化为单独的
x/y/z浮点数(JSON 没有 Vector 类型) - 所有文件操作都检查返回码,并在失败时调用
push_error() -
_migrate()处理从 0 到当前版本的所有版本,并逐步应用迁移 - 绝不将资源文件(.tres/.res)用于由玩家控制的存档数据
- 存在用于 UI 槽位管理的
get_save_slots()和delete_save()辅助函数 - 可存档节点使用跨会话保持不变的稳定 ID