关于 godot-game-architecture
Godot Game Architecture 是用于设计 Godot 项目中游戏状态、场景流程、管理器和持久化的技能。它强调为每项状态指定唯一权威所有者,并在调整架构前检查生命周期及存档读写行为。
主要功能
- 01区分定义、运行时、表现和快照状态
- 02按生命周期指定状态所有者
- 03指导场景与自动加载的职责划分
- 04设计场景转换与覆盖层
- 05版本化存档边界
- 06验证生命周期与持久化
适用场景
- 01判断状态应由场景还是自动加载管理
- 02规划游戏流程转换时的重置行为
- 03设计存档、读档与迁移边界
- 04排查过期引用或残留场景节点
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pbzona/ godot-skills --skill godot-game-architecture安装后在 Claude Code 中输入/godot-game-architecture确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/managers-and-scene-flow.mdpersistence-boundaries.mdstate-and-data-ownership.md详细介绍
Godot 游戏架构
让每项状态都由一个唯一权威所有者管理,并将其生命周期限定在满足游戏流程需求的最小范围内。
范围
在以下情况下使用此技能:
- 根据生命周期对状态分类,并选择其权威写入者。
- 分离静态定义、实时模拟状态、表现状态和持久化快照。
- 判断协调器应属于场景还是自动加载项。
- 定义管理器职责和公开的变更边界。
- 协调菜单、游戏过程、结果、重新加载和叠加场景流程。
- 设计新会话、重置、检查点、保存、加载、迁移和损坏数据处理逻辑。
- 防止场景切换时遗留节点或保留过期引用。
不要使用此技能处理基本节点选择、场景实例化、自定义资源语法、输入映射设置或编辑器导航;请使用基础技能。不要使用此技能讲解 SOLID、信号机制、命令或对象池;请使用编程模式技能。架构可以选择事件或组件边界,但其实现细节由模式技能负责。
设计前先检查
- 找到
project.godot,检查config/features,确认 Godot 4.x 的具体目标版本。 - 阅读
[application],确定主场景;阅读[autoload],盘点进程生命周期节点及其顺序。 - 检查项目中的场景、脚本、资源和数据布局。遵循现有的命名、文件夹、类型和依赖约定。
- 追踪当前所有场景切换和叠加层。记录由谁发起、哪些内容会被释放、哪些内容会保留,以及下一场景的预期。
- 建立状态清单。为每个值记录其写入者、读取者、生命周期、重置规则、定义来源,以及是否会持久化。
- 搜索对共享字段的直接写入、全局查找、
get_tree().root.add_child()、管理器引用、用户文件访问和启动时发出的信号。 - 重现基线流程:新鲜启动、新游戏、场景切换、重试、返回菜单,以及可用时的保存/加载。
- 修改架构或所有权前,检查现有测试和所有保存数据样例。
评估现有所有者和自动加载项之前,不要添加新的管理器。
对状态分类
区分以下四种概念:
- 定义数据: 在实例间共享的编写时数据,通常以资源表示,例如物品费用或单位基础速度。
- 运行时状态: 该实体、房间、对局或会话中的可变数据,例如当前生命值或已探索房间。
- 表现状态: 临时的视图细节,例如选中的标签页、动画进度或可见的工具提示。
- 快照数据: 跨越持久化边界的原始类型版本化数据。
不要让同一份共享资源同时承担这四种用途。尤其不要通过修改定义资源来保存运行时进度,因为这可能影响所有使用者,并增加保存处理的复杂度。
按生命周期分配所有权
选择最近的稳定所有者:
- 实体状态归实体或其专职组件所有。
- 房间或关卡状态归该房间/关卡协调器所有。
- 对局状态归对局根节点或其拥有的对局模型所有。
- 跨关卡场景延续的运行状态归在这些场景切换期间持续存在的会话所有者所有。
- 玩家档案进度和设置归档案/设置服务所有,并通过明确的持久化 API 进行管理。
- UI 负责展示状态,不应成为游戏权威状态的存储位置。
每项状态值只允许有一个写入者。其他系统通过方法请求变更,并通过读取或事件观察结果。避免让所有场景都能直接编辑公共字典。
确定管理器的生命周期
如果某个管理器的状态应随场景一同消失,就让它仅存在于该场景中。关卡导演、遭遇追踪器或比赛裁判通常应放在游戏根节点下。
仅在至少满足以下一个条件时,才使用自动加载:
- 该功能必须在当前场景替换前后都可用。
- 多个互不相关的根场景需要使用同一个进程生命周期服务。
- 它负责协调场景替换本身。
- 它持有生命周期按定义跨越这些场景的会话或个人资料状态。
自动加载不得在场景退出后保留该场景中的普通节点。应存储纯状态、稳定 ID,或重新获取引用。提供显式的 start_new_*、reset 和 restore 方法;进程生命周期不等于重置策略。
设计场景流转
- 由一个协调器统一负责替换当前场景。
- 将目标表示为导出的
PackedScene值或集中式路由表,而不要在 UI 和角色中反复使用字符串路径。 - 防止同一帧内由多个输入或结束条件触发重复转场。
- 将场景替换和叠加视为不同操作。替换互斥的根场景;将暂停、对话和加载叠加层放在明确指定的所有者下。
- 将运行时创建的游戏节点放在当前场景下,以便场景替换时释放它们。
- 如果初始化需要访问传入场景中的节点,请等待
SceneTree.scene_changed。 - 在场景就绪后获取初始状态;不要依赖迟到的监听器可能错过的全局启动事件。
- 明确死亡、重试、下一关和返回菜单时,是否保留或重置运行状态。
定义持久化边界
- 保存快照,而不是节点、可调用对象、信号连接或实时资源引用。
- 将游戏对象转换为包含稳定 ID 的基本类型字典或数组。
- 将用户数据存储在
user://下,绝不存储在已导入的res://内容中。 - 包含架构版本,并为每个受支持的旧版本定义迁移或拒绝策略。
- 在修改实时状态前,验证类型、范围、ID 和必需的关系。
- 先恢复到干净的模型,再根据该模型构建或更新场景。
- 将磁盘 I/O 和序列化放在游戏实体之外。
- 明确保存时机和失败处理方式;不要让每个子系统各自写入。
实施工作流
- 仅为受影响的状态和流程编写所有权图。
- 定义权威所有者范围精简的公共 API。
- 在保留当前行为的同时,将所有修改路由到该所有者。
- 让视图根据当前快照初始化,然后观察后续变化。
- 将协调器放在其管理的生命周期范围内;不要为了方便而将场景局部状态提升为自动加载。
- 集中处理场景替换,并为每条路由定义重置语义。
- 将快照转换、验证、版本控制和存储作为独立步骤添加。
- 只有在所有读取方都使用权威状态后,才移除过时的重复状态。
- 测试生命周期和持久化矩阵,而不只是顺利流程。
验证
运行现有项目检查,并在适用时测试以下情况:
- 没有用户数据时全新启动。
- 直接运行主场景,以及通过已配置的入口场景正常启动。
- 同一进程中已有上一次运行记录时开始新游戏。
- 多次进行菜单、游戏、结果、重试和下一关之间的切换。
- 同一帧内发起两次场景切换请求。
- 定时器、
await或运行时创建的节点仍处于活动状态时退出场景。 - 状态已更改后才创建 UI;UI 仍必须显示当前值。
- 将存档加载到干净会话中的往返测试。
- 缺失、截断、格式错误、版本未知及部分有效的存档数据。
- 作者内容重命名或删除后,稳定 ID 的解析情况。
- 配置文件/设置的持久化不会意外持久化运行状态。
- 多次循环后远程场景树和对象的数量;不应残留旧根节点或场景引用。
报告已验证的状态所有者、重置策略、场景切换流程和架构版本。
故障模式
- 所有内容都变成自动加载: 便利性取代了所有权。将状态移至生命周期范围最窄的场景或模型中。
- 管理器成了杂物袋: 不相关的系统直接写入字段。拆分相互独立的功能,并公开修改方法。
- 进入时 UI 已过时: 它等待的是过去发生的事件。初始化时读取当前状态,然后订阅变更。
- 新游戏保留旧值: 进程生命周期内的状态没有明确的重置路径。
- 场景切换导致角色泄漏: 节点被挂载到
current_scene之上,或某个长生命周期对象仍持有它们。 - 自动加载访问了缺失的 HUD 节点: 全局初始化早于目标场景就绪。应在
scene_changed后响应,或由场景读取状态。 - 两个所有者互相矛盾: 状态在 UI、管理器、实体或资源中重复。确定唯一权威来源,其余内容由此推导。
- 共享定义被修改: 用作模板的
.tres也保存了单次运行的进度。将定义模型与运行时模型分开。 - 加载只应用了一部分: 验证和修改交错进行。先解析并验证完整的临时快照。
- 旧存档导致崩溃: 缺少架构版本、迁移、默认值或未知 ID 处理策略。
- 场景切换字符串不一致: 路径散落在按钮和角色中。集中管理路由或导出场景资源。