mcpField
G
godot-master

godot-master

github.com/thedivergentai开发9075.0k 次安装2 周前更新
代码仓库

关于 godot-master

godot-master 是面向 Godot 4.7+ 项目架构师和开发者的知识中心,提供架构决策框架、专家工作流,以及引擎系统和游戏类型相关指导。它不作为版本迁移日志使用。

主要功能

  1. 01Godot 4.7+ 架构指导
  2. 02状态归属与信号设计
  3. 03按场景选择架构方案
  4. 04项目搭建工作流
  5. 05跨系统及游戏类型模式

适用场景

  1. 01规划 Godot 项目架构
  2. 02设计模块化实体和状态转换
  3. 03为特定游戏类型选择系统方案
  4. 04通过 Godot CLI 构建工具搭建项目

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/thedivergentai/game-dev-agentic-skills --skill godot-master

安装后在 Claude Code 中输入/godot-master确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
2d-animation-cutout-and-skeletal.md
2d-animation-expert-techniques.md
2d-animation-migration-notes.md
2d-animation-signals-and-frame-events.md
2d-animation.md
2d-physics-area2d-and-queries.md
2d-physics-collision-layers-masks.md
2d-physics-migration-notes.md
2d-physics.md
3d-lighting-environment-and-fog.md
3d-lighting-gi-and-bake-recipes.md
3d-lighting-migration-notes.md
3d-lighting.md
3d-materials-migration-notes.md
3d-materials-pbr-workflows.md
3d-materials.md
3d-world-building-gridmap-and-csg.md
3d-world-building-migration-notes.md
3d-world-building-streaming-and-procgen.md
3d-world-building.md
ability-system-elite-ability-patterns.md
ability-system-migration-notes.md
ability-system.md
adapt-2d-to-3d-migration-notes.md
adapt-2d-to-3d-migration-recipes.md
adapt-2d-to-3d.md
adapt-3d-to-2d-dimension-reduction.md
adapt-3d-to-2d-migration-notes.md
adapt-3d-to-2d.md
adapt-desktop-to-mobile-migration-notes.md

详细介绍

Godot Master:首席架构师知识中心

每个章节都通过聚焦 知识增量——基础模型已有知识与资深 Godot 工程师在交付真实产品过程中积累的知识之间的差距——来证明其价值。

知识库目标版本 — Godot 4.7+

所有领域技能镜像均以 Godot 4.7+(稳定版)为目标。对于任何引擎版本升级(1.x/2.x legacy → 3→4 → 逐步升级 4.x),请使用 godot-version-migration——不要把本知识中心当作迁移变更日志。

进行分类时,请留意以下跨领域的 4.7 提示:AreaLight3D / HDR → 3D Lighting;Asset Store 与 Asset Library → 导出/平台模块;RichTextLabel ImageUnit、输入设备 ID 常量、Jolt 行为 → 迁移中心模块说明。


🧠 第 1 部分:专家思维框架

“谁负责什么?”——架构健康检查

在编写任何系统之前,请针对每一份状态回答以下三个问题:

  • 谁拥有数据?(StatsComponent 拥有生命值,而不是 CombatSystem)
  • 谁可以修改它?(只有所有者能通过 apply_damage() 这样的公共方法修改)
  • 谁需要知道它已发生变化?(任何监听 health_changed 信号的对象)

如果你无法针对每个状态变量回答这三个问题,说明你的架构存在耦合问题。这不是 OOP 封装——这是 Godot 特有的,因为信号系统就是强制执行机制,而不是访问修饰符。

Godot“分层蛋糕”

将每项功能划分为四层。信号只向上流动,绝不向下:

┌──────────────────────────────┐
│  PRESENTATION (UI / VFX)     │  ← Listens to signals, never owns data
├──────────────────────────────┤
│  LOGIC (State Machines)      │  ← Orchestrates transitions, queries data
├──────────────────────────────┤
│  DATA (Resources / .tres)    │  ← Single source of truth, serializable
├──────────────────────────────┤
│  INFRASTRUCTURE (Autoloads)  │  ← Signal Bus, SaveManager, AudioBus
└──────────────────────────────┘

关键规则:表现层绝不能直接修改数据。基础设施只能通过信号进行通信。如果某个 Label 节点调用了 player.health -= 1,说明架构已被破坏。

信号总线分级架构
  • 全局总线(Autoload):仅用于生命周期事件(match_started、player_died、settings_changed)。代价是调试范围扩大——事件数量应限制在 15 个以内。
  • 作用域功能总线:每个功能文件夹都有自己的总线(例如,CombatBus 仅供战斗节点使用)。这是可扩展的折中方案。
  • 直接信号:单个场景内的父子通信。绝不要跨场景边界通信。
🔗 “智能互联”原则

专家系统的定义不在于彼此孤立,而在于其负载合成能力。

  • 物理 → 性能:PhysicsServer2D 和 RenderingServer 可绕过 SceneTree 节点开销。用于处理 1,000+ 个子弹或粒子,实现 O(1) 处理。
  • 动画 → 物理:AnimationTree.get_root_motion_position() 会将动画位移转换为物理 velocity,避免复杂移动中的“脚底打滑”。
  • 数据 → 响应性:序列化的 Resource 对象(如 Stats)在修改时会发出信号,让 UI 自动更新,同时避免紧密耦合。
  • 资源 → 生成:基于 Dictionary 的 O(1) 缓存(在 ResourceLoader 异步阶段预加载)可避免生成物品或敌人时出现 I/O 卡顿。
  • 移动端 → 视觉效果:在加载画面期间实例化隐藏效果,以强制编译 GPU 着色器管线,避免运行时帧卡顿。
  • 网络 → 带宽:使用位打包将数据写入 PackedByteArray 进行同步,而非使用 JSON/Strings,将数据包控制在 100 字节以内。
  • 类型合成:
    • Shooter:严格使用 intersect_ray()(直接空间状态),而非 RayCast3D 节点,性能可提升 100 倍。
    • RPG:伤害遵循 base * pow(scaling, level),以支撑游戏后期的成长。
    • RTS:根据群组的质心移动,并使用 Relative Offset 保持阵型完整。
    • Metroidvania:使用 ResourceLoader.load_threaded_request() 实现无缝房间切换。
    • Platformer:必须加入 Jump Buffering(约 0.15s)和 Coyote Time,带来专业的操作手感。
    • Simulation:使用 Tick Manager 批量处理;避免对每个实体单独调用 _process,以支持数千个单位。
    • Romance:使用多轴好感度(吸引力、信任、舒适度)映射复杂的叙事分支。
    • Architecture:Signal Architecture 必须严格遵循“信号向上,调用向下”,以消除场景间的循环耦合。

🧭 第 2 部分:架构决策框架

主决策矩阵
场景策略必读技能链权衡
快速原型事件驱动单体阅读:基础 → 自动加载。不要加载类型或平台参考资料。启动快,有变成意大利面代码的风险
复杂 RPG组件驱动阅读:组合 → 状态 → RPG 属性。不要加载多人游戏或平台参考资料。前期设置繁重,可无限扩展
大型开放世界资源流式加载阅读:开放世界 → 保存/加载。另请加载性能。I/O 复杂,超过 10K 单位后会出现浮点精度抖动
服务端权威多人游戏确定性阅读:服务端架构 → 多人游戏。不要加载单人游戏类型参考资料。延迟高,反作弊安全性强
移植到移动端/Web自适应响应式阅读:UI 容器 → 从桌面适配到移动端 → 移动平台。UI 复杂度高,覆盖面广
应用 / 工具应用组合阅读:应用组合 → 主题。不要加载游戏专用参考资料。与游戏采用不同范式
恋爱 / 约会模拟好感度经济系统阅读:恋爱 → 对话 → UI 富文本。UI/叙事密度高
秘密 / 彩蛋有意混淆阅读:秘密 → 持久化。提升社区参与度,有调试风险
收集任务寻宝逻辑阅读:收集 → Marker3D 放置。提升玩家留存率,推动探索
季节性活动运行时注入阅读:复活节主题 → 材质替换。快速打造品牌风格,不污染资源
类魂式死亡机制风险与回报式复活阅读:复活/尸体寻回 → 3D 物理。紧张感强,有令玩家受挫的风险
波次制动作游戏战斗节奏循环阅读:波次 → 战斗。紧张感逐步升级,需设计遭遇战
平衡 / 难度 / 经济节奏蒙特卡洛平衡实验室阅读:资源 → 经济系统 → 战斗 / RPG 属性 / 波次(按需选择)→ 蒙特卡洛平衡器 → 测试 → 构建器。统计严谨;抽象模拟必须对照无头 Godot 进行校准
生存经济系统采集循环阅读:采集 → 库存。资源稀缺,循环可持续
竞速 / 速通验证循环阅读:计时赛 → 输入缓冲 → 竞速类型。精度要求高,推动幽灵记录竞争
恐怖 / 潜行紧张感管理阅读:恐怖类型 → 潜行类型 → 音频。营造氛围,凸显玩家的脆弱感
卡牌 / 棋盘游戏规则执行阅读:卡牌游戏类型 → 回合系统。状态确定性强,UI 工作量大
模拟 / RTS批处理阅读:模拟类型 → RTS 类型 → 性能。单位数量多,逻辑为 O(1)
HDR / 电影级视觉效果显示管线阅读:3D 光照 → 桌面平台 → 着色器。在项目设置中启用视口 HDR。需要针对平台调校色调映射
矩形区域光AreaLight3D阅读:3D 光照 → 3D 材质。优先使用 AreaLight3D,而非自发光+GI 变通方案。需要 Forward+ 渲染器才能获得完整画质
移动端触控控制原生摇杆阅读:移动平台 → 从桌面适配到移动端。使用内置虚拟摇杆(4.7+)。减少对插件的依赖
插件 / 资源发现资源商店阅读:项目基础 → 导出构建。资源商店取代 Asset Library。商店 UI 仍处于 Beta 阶段——请逐个核实插件的许可
Agent 视觉 / 可视化 QA捕获 → WebP → 评估标准阅读:Agent 视觉。捕获截图资源、窗口/区域/屏幕,或临时编辑器桥接——然后进行结构化审查。不要加载类型参考资料。仅限主机端;绝不使用 Autoload / 绝不保留暂存插件
制品 → Godot 项目先建台账,再创建存根阅读:GDAS-reader → REA。在存根指明类型之前,不要加载类型参考资料。仅创建存根;未知行为保持为 pass
“何时不该使用 Node”的决策

这是影响最大的专家级决策之一。Godot 文档明确指出“避免事事都使用节点”:

类型适用场景成本专家用例
Object自定义数据结构、手动内存管理最轻。必须手动调用 .free()。自定义空间哈希映射、类似 ECS 的数据存储
RefCounted临时数据包、会自动删除的逻辑对象没有剩余引用时自动删除。DamageRequest、PathQuery、AbilityEffect——不需要场景树的逻辑数据包
Resource可序列化且支持检查器的数据比 RefCounted 略重。负责 .tres I/O。ItemData、EnemyStats、DialogueLine——设计师应能在检查器中编辑的任意数据
Node需要 _process/_physics_process,需要存在于场景树中最重——每个节点都有 SceneTree 开销。仅用于需要逐帧更新或空间变换的实体

专家模式:所有逻辑数据包和数据容器都使用 RefCounted 子类。仅将 Node 用于必须存在于空间树中的对象。对于复杂系统,这能将场景树开销减半。


🔧 第 3 部分:核心工作流

工作流 1:专业脚手架

从空项目到可用于生产环境的容器。

必须 — 阅读整个文件:基础

  1. 按功能(/features/player/、/features/combat/)而非类类型组织。player/ 文件夹包含玩家的场景、脚本、资源和测试。
  2. 阅读:信号架构 — 创建包含少于 15 个事件的 GlobalSignalBus 自动加载。
  3. 阅读:GDScript 精通 — 在 Project Settings → GDScript → Debugging 中启用 untyped_declaration 警告。
  4. 应用**项目模板**,获取基础 .gitignore、导出预设和输入映射。
  5. 使用 Builder(builder_create_scene.py、builder_add_node.py、builder_save_scene.py),通过 Godot CLI 以编程方式生成场景层级。

注意

工作流 1 禁止事项

  • 绝不在逻辑脚本中使用 res:// 路径。使用 @export_file 或 @export_dir,确保资源移动后仍然有效。
  • 绝不在 _init() 中初始化子节点。此时场景树尚未就绪。请使用 _ready() 或 @onready。
  • 绝不保留“Default”项目的 Physics Ticks 设置。将其设为 60 以保持一致,或使用 Engine.physics_ticks_per_second 实现自适应逻辑。
  • 绝不在 _process() 中使用 print() 进行调试;请使用 Debugger 或 push_error(),避免帧耗时突增。

脚手架搭建期间不要加载战斗、多人游戏、游戏类型或平台相关参考资料。

工作流 2:实体编排

构建模块化、可测试的角色。

强制链路 — 全部阅读:组合 → 状态机 → CharacterBody2D 或 Physics 3D → Animation Tree 不要加载实体相关工作的 UI、Audio 或 Save/Load 参考资料。

  • 状态机查询 InputComponent,绝不直接处理输入。这样即可在不重构的情况下切换 AI/玩家。
  • 状态机只处理状态转换。逻辑应放在组件中。MoveState 告知 MoveComponent 执行操作,而不是反过来。
  • 每个实体都必须通过 F6 测试:按下“运行当前场景”(F6)必须能够正常运行,不发生崩溃。如果发生崩溃,说明实体依赖于场景外部内容。

注意

工作流 2 绝对禁止清单

  • 绝不要调用 parent.do_thing()。如果父节点发生变化,实体就会出问题。应改为发出信号 request_action。
  • 绝不要使用 _process 移动。使用 _physics_process,以避免在可变刷新率显示器上发生抖动。
  • 绝不要硬编码动画名称。使用 StringName 常量或 Resource 映射,以便在 AnimationPlayer 中轻松重命名。
  • 绝不要使用绝对路径调用 get_node()。使用 %UniqueName,以便在重构树结构后仍能正常工作。
工作流 3:数据驱动系统

通过 Resources 连接 Combat、Inventory 和 Stats。

强制链路 — 全部阅读:资源模式 → RPG 属性 → Combat → Inventory

  • 创建一个继承自 Resource 的 ItemData.gd。将其实例化为 100 个 .tres 文件,而不是编写 100 个脚本。
  • HUD 绝不直接引用 Player。它会监听 Signal Bus 上的 player_health_changed。
  • 对所有 @export Resource 变量启用“Local to Scene”,或在 _ready() 中调用 resource.duplicate()。未能做到这一点是第 8 部分中的 Bug #1。

注意

工作流 3 绝对禁止清单

  • 绝不要在 Signal Bus 中传递 Node 引用。对象会被释放;长期跟踪时,RID 或 ID 更安全。
  • 绝不要在运行时通过代码修改 .tres 文件(这会修改磁盘文件)。修改前务必调用 .duplicate()。
  • 绝不要使用 Array 进行高频搜索。使用以 StringName 为键的 Dictionary,实现 O(1) 查找。
  • 绝不要使用 float 表示物品数量或精确的资源跟踪;应使用 int,并在显示时进行缩放。
工作流 4:持久化流程

强制阅读:Autoload 架构 → Save/Load → 场景管理

  • 使用字典映射进行序列化。添加新字段时,旧存档文件绝不能损坏——使用 .get("key", default_value)。
  • 对于程序生成的世界:保存 Seed 和修改项的 Delta-List,而非整张地图。100 MB 的世界可以只需 50 KB 的存档。

注意

工作流 4 绝对禁止清单

  • 绝不要保存整个 Object 或 Node 实例。它们包含临时指针。应将数据提取到 Dictionary 或自定义 Resource 中。
  • 绝不要对需要严格类型的数据(例如 Vector2)使用 JSON。对于结构化的 Godot 类型,请使用 var_to_bytes 或 ConfigFile。
  • 绝不要因自动存档而阻塞主线程。使用 Thread 或 WorkerThreadPool 序列化大型字典。
  • 绝不要在导出的项目中保存到 res://;持久化数据必须使用 user://。
工作流 5:性能优化

必须遵循:调试/性能分析 → 性能优化

先诊断再优化(绝不盲目优化):

  1. 脚本耗时高 → 使用内置 Profiler 进行性能分析。检查是否有数百个节点在调用 _process。改用单一管理器模式或 Server API(参见第 6 部分)。
  2. 绘制调用过多 → 对重复几何体使用 MultiMeshInstance。使用 ORM 纹理合并材质。
  3. 物理卡顿 → 将碰撞简化为基本形状。加载 2D 物理 或 3D 物理。检查移动逻辑是否误用了 _process,而不是 _physics_process。
  4. VRAM 使用过量 → 将纹理改为 VRAM 压缩格式(桌面端使用 BPTC/S3TC,移动端使用 ETC2)。绝不发布原始 PNG。
  5. 间歇性帧尖峰 → 通常由 GC 回收、同步 load() 或 NavigationServer 重新计算导致。使用 ResourceLoader.load_threaded_request()。

注意

工作流 5 绝对禁止清单

  • 绝不在 _process 中使用 get_nodes_in_group()。这是每帧执行的 O(n) 操作。在 _ready() 中缓存数组。
  • 绝不使用 Area2D 信号处理“停留”逻辑。应定期调用 get_overlapping_bodies(),或在管理器级别使用 PhysicsServer 检查。
  • 绝不在性能分析前优化。如果有 2000 次绘制调用拖垮 GPU,那么 1 ms 的脚本耗时无关紧要。
  • 绝不在热点路径中使用 load();严格使用 preload,或使用 ResourceLoader 进行异步加载。
工作流 6:跨平台适配

必须遵循:输入处理 → 桌面端改为移动端 → 移动平台 还需按需阅读:桌面平台、Web 平台、主机平台、VR 平台。

  • 使用 InputManager 自动加载,将所有输入类型转换为规范化操作。绝不直接读取 Input.is_key_pressed()——这会阻碍控制器和触控支持。
  • 移动端触控目标:物理尺寸至少为 44px。对于带刘海/挖孔的设备,使用 MarginContainer 并处理安全区域。
  • Web 导出:Godot 的 AudioServer 需要用户交互后才能首次播放(浏览器策略)。通过“点击开始”界面处理此问题。

注意

工作流 6 绝对禁止清单

  • 绝不使用 OS.get_name() 检测功能。应使用 OS.has_feature("mobile") 或自定义功能标签,以处理“SteamDeck”等细分平台。
  • 绝不假定特定的宽高比。始终结合 Anchor 节点使用 Expand 或 Keep Aspect。
  • 绝不在移动端/Web 上使用仅适用于桌面端的着色器(例如复杂的深度采样),除非提供 GLES3/Compatibility 次级路径。
  • 绝不在桌面端构建中忽略 physical_keycode;它能确保键盘布局(AZERTY/QWERTY)不会导致移动操作失效。
  • 绝不将未经清理的字符串传递给 JavaScriptBridge.eval()——这可以防止 Web 构建中的脚本注入。请使用 sanitize_js_string() 辅助函数。
工作流 7:程序化生成

必须:Procedural Gen → Tilemap Mastery 或 3D World Building → Navigation

  • 始终使用带有固定 seed 的 FastNoiseLite 资源,确保生成结果具有确定性。
  • 切勿在主线程上烘焙 NavMesh。请使用 NavigationServer3D.parse_source_geometry_data() + NavigationServer3D.bake_from_source_geometry_data_async()。
  • 对于无限世界:区块加载必须使用 WorkerThreadPool 在后台线程中进行。在场景树之外构建场景区块,然后在主线程上调用 add_child.call_deferred()。

注意

工作流 7 禁止事项

  • 切勿为“背景”噪声实例化节点。对于数千个细小细节,请使用 MultiMeshInstance 或在 _draw 中使用绘制循环。
  • 切勿因一处改动而重新生成整张地图。使用“脏区块”系统,仅更新实际发生变化的部分。
  • 切勿在使用 concave_polygon_shape 时与网格生成同帧放置碰撞体,这会使物理线程卡顿。
  • 切勿每帧都为所有单位执行寻路查询。请使用 NavigationAgent,并通过计时器更新 target_position。
工作流 8:多人游戏架构

必须阅读:Single→Multiplayer → Networking → Server Arch 不要加载单人游戏类型蓝图。

  • 客户端发送输入,服务端计算结果。客户端绝不能决定伤害、位置变化或库存变更。
  • 使用带服务端校正的客户端预测:在本地预测,并根据服务端快照进行修正。可隐藏最多约 150 ms 的延迟。
  • 在 Godot 4 中,MultiplayerSpawner 负责处理复制。请按场景配置,而非全局配置。

注意

工作流 8 禁止事项

  • 切勿在未验证的情况下信任 rpc_id(1, ...)(客户端到服务端)。遭到入侵的客户端可以发送 damage = 999999。
  • 切勿直接复制 _process 变换。应复制 Input 向量,并在双方模拟移动。
  • 切勿将 TCP 用于高频数据包(移动)。请使用 UDP / ENet,并通过插值处理丢包。
  • 切勿同步每个投射物;请对视觉效果使用客户端预测,并仅通过 RPC 发送“开火”事件。
  • ReflectionProbe 与 VoxelGI 和 SDFGI 的对比:探针成本低且为静态,VoxelGI 为中等成本且需烘焙,SDFGI 成本高且为动态。请根据平台预算进行选择(参见第 5 部分)。
工作流 9:响应式 UI 与专家级主题(审计已验证)

强制链路:UI 容器 → UI 主题 → 富文本 → 缓动

  1. F6 原则:每个 UI 场景都必须能够独立测试。仅在背景上使用 MOUSE_FILTER_STOP,子节点使用 PASS。
  2. 留白空间:使用 add_theme_constant_override("separation", X),而非手动添加内边距。
  3. 自适应缩放:使用 ui_containers_responsive_layout_builder.gd,根据断点切换移动端/桌面端布局。
  4. 生命周期安全:不要在同一帧内滚动到新子节点。修改 scroll_vertical 前,先执行 await get_tree().process_frame。
  5. 数据集成:使用 Resource-to-UI 绑定;UI 节点必须是无状态的投影层。

注意

工作流 9 禁止事项

  • 禁止使用绝对像素偏移。在 4K 或超小移动屏幕上,UI 会变得难以辨认。请使用 Container 尺寸设置。
  • 禁止深层嵌套 MarginContainers。这会导致 Inspector 无法使用。请使用单个 Theme 资源统一设置整个项目的边距。
  • 禁止将 UI 按钮直接连接到游戏逻辑。UI 发送“Signal”,由 PlayerController 监听。这可以防止删除 UI 时发生崩溃。
  • 禁止使用 _process() 将 UI 元素移动到目标位置。请使用 Tween,避免卡顿和帧率依赖。
  • 禁止让透明容器的 mouse_filter 保持为 STOP;它会“吞掉”后方所有内容的点击。
  • 禁止在未验证 res:// 前缀和安全扩展名(.tres、.res、.theme)的路径上使用动态 load()——这可以防止任意代码/资源执行。
工作流 10:电影级光照与 VFX(审计已验证)

强制链路:3D 光照 → 粒子 → 3D 材质 → 着色器

  1. GI 选择:室内场景使用 VoxelGI,开放世界使用 SDFGI。禁止同时启用并让两者重叠。
  2. 阴影预算:投射阴影的 DirectionalLight 最多 2 个。移动端补光使用 3d_lighting_fake_gi_bounce.gd。
  3. VFX 生命周期:优先使用 finished 信号,而非计时器。使用 restart() 重新运行,避免异步 GPU 卡顿。
  4. 优化:使用 ORM Texture 打包(AO/Rough/Metal),节省 GPU 缓存和纹理槽位。
  5. 批处理:使用 Instance Uniforms 为数千个实例创建材质变体,而不会增加绘制调用开销。

注意

工作流 10 禁止事项

  • 禁止缩放 CollisionShape 节点;应严格缩放 Shape Resource,以避免物理抖动。
  • 禁止对镂空网格(树叶/栅栏)使用 TRANSPARENCY_ALPHA;请使用 ALPHA_SCISSOR,避免排序伪影。
  • 禁止在游戏过程中对 CSG 节点进行动画处理;这会强制进行开销巨大的 CPU 几何体重新计算。
  • 禁止在 2D 风格的游戏中使用实时全局光照(SDFGI/VoxelGI)。请使用 DirectionalLight2D 和 CanvasModulate。
  • 禁止忽略 Camera3D 的近裁剪面/远裁剪面设置;设置不当会导致大型世界中出现 Z-fighting。
工作流 11:以编程方式构建场景(Builder)

必须:Builder 仅用于批量操作或复杂的程序化框架搭建。 执行繁重的 CLI 自动化时,优先使用独立的 godot-builder skill。

  1. 步骤 1:动手操作磁盘前,先在纸上或 Markdown 中拟定节点层级结构。
  2. 步骤 2:使用 builder_create_scene.py 定义根节点和 .tscn 路径。
  3. 步骤 3:使用 builder_add_node.py 添加子节点。为每个节点设置 owner,确保序列化时保留这些节点。
  4. 步骤 4:务必调用 builder_run_project.py 或 builder_launch_editor.py,确认场景可以正常加载。
  5. 专家规则:使用 Builder 构建结构(节点、名称、继承),然后使用 GDScript 构建行为。

注意

工作流 11 绝对禁止事项

  • 绝对不要跳过层级设计,直接使用 builder_add_node.py——这会导致场景变得一团乱麻。
  • 绝对不要在脚本或场景属性中使用绝对文件系统路径;只能使用 res://。
  • 绝对不要添加未指定 Shape 资源的 CollisionShape2D/CollisionShape3D——单独的节点不起任何作用。
  • 绝对不要在批量写入场景后跳过验证;请使用 builder_run_project.py / builder_launch_editor.py 进行验证。
安全:边界标记与验证

当 Agent 在写入文件前摄取不可信的场景/数据文本时:

  1. 边界标记:使用 <<<CONTEXT_START>>> 和 <<<CONTEXT_END>>> 包裹分析内容。
  2. 清理:节点名称只能包含字母数字字符和下划线。路径必须以 res:// 开头。
  3. 验证:修改前确认场景存在。

🚫 第 4 部分:专家绝对禁止事项

每条规则都包含不显而易见的原因——只有实际交付过项目的人才能学到的经验。

  1. 绝对不要使用 get_tree().root.get_node("...")——绝对路径会在任意祖先节点重命名或重新设定父节点时失效。使用 %UniqueNames、@export NodePath 或基于信号的查找方式。
  2. 绝对不要在循环或 _process 中使用 load()——同步磁盘读取会阻塞整个主线程。小型资源可在脚本顶部使用 preload(),大型资源则使用 ResourceLoader.load_threaded_request()。
  3. 外部引用仍存在时,绝对不要调用 queue_free()——持有引用的父节点或数组会引发 “Deleted Object” 错误。在 _exit_tree() 中清理引用,并在释放对象前将其设为 null。
  4. 绝对不要将游戏逻辑放在 _draw() 中——_draw() 在渲染线程上调用。修改游戏状态会与 _physics_process 产生竞态条件。
  5. 对于 1000 个以上相互重叠的对象,绝对不要使用 Area2D——每次重叠检查都会产生 O(n²) 的宽相成本。对于弹幕游戏模式,请使用 ShapeCast2D、PhysicsDirectSpaceState2D.intersect_shape() 或 Server API。
  6. 绝对不要从组件修改外部状态——如果 HealthComponent 调用 $HUD.update_bar(),删除 HUD 会导致游戏崩溃。组件应发出信号,由监听者决定如何响应。
  7. 绝对不要在 _physics_process 中使用 await——await 会让出执行权,导致物理步跳过帧。将异步操作移到由信号触发的独立方法中。
  8. 绝对不要在高频路径的字典查找中使用 String 键——字符串哈希的复杂度为 O(n)。使用 StringName(&"key")进行 O(1) 指针比较,或使用整数枚举。
  9. 绝对不要保存指向已释放对象的 Callable 引用——这会导致程序无提示地崩溃或抛出错误。在 _exit_tree() 中断开信号,或使用 CONNECT_ONE_SHOT。
  10. 对于 1000 个以上的实体,绝对不要使用 _process——每次 _process 调用都会产生逐节点的 SceneTree 开销。使用单个 Manager._process 遍历数据结构数组(面向数据的模式),或直接使用 Server API。
  11. 绝对不要在可能被释放的节点上使用 Tween——如果 Tween 运行期间节点被 queue_free(),就会报错。在 _exit_tree() 中终止 Tween,或绑定到 SceneTree:get_tree().create_tween()。
  12. 绝对不要在 _process 中向 RenderingServer 或 PhysicsServer 请求数据——这些 Server 异步运行。调用 getter 函数会强制触发同步停顿,严重影响性能。这些 API 特意设计为在高频路径中只写不读。
  13. 绝对不要用 call_deferred() 掩盖初始化顺序错误——这会掩盖架构问题(依赖场景树顺序)。使用显式初始化信号或 @onready 修复实际依赖。
  14. 绝对不要创建循环信号连接——节点 A 连接到 B,B 又连接到 A。这会在首次发出信号时造成无限循环。使用中介者模式(信号总线)打破循环。
  15. 绝对不要让继承层级超过 3 层——超过 3 层后,调试 super() 调用链会变得极其困难。使用组合(Node 子节点)添加行为。
  16. 在物理运算密集的游戏类型(FPS/ARPG)中,绝对不要使用 _process 进行命中检测或移动;务必使用 _physics_process,以确保碰撞检测不受帧率影响。
  17. 对于持久化游戏状态(Health、XP、Inventory),绝对不要信任客户端的授权信息。应完全通过服务器权威机制或安全校验和处理。
  18. 高频运行时检查中,绝对不要使用普通字符串;务必使用 StringName(&"active"),以避免 O(n) 哈希开销。
  19. 在单位数量众多的游戏(RTS/MOBA)中,绝对不要每帧手动处理 RVO 避让;将其交由 NavigationAgent 的内部线程处理。
  20. 绝对不要因过程式生成或繁重的 I/O 操作而阻塞主线程;务必将任务交给 WorkerThreadPool。
  21. 对于用于独立实例(例如敌人属性)的 Resources,绝对不要忽略 Local-to-Scene;否则会导致所有实例之间出现共享内存错误。
  22. 绝对不要用 float 表示货币;务必使用整数分(Integer Cents),避免复杂经济系统中的精度偏差。
  23. 绝对不要在 physics_frame 之前设置 target_position;导航地图在 _ready() 期间尚未准备就绪。
  24. 对于大型镂空表面(如树叶),绝对不要使用 TRANSPARENCY_HASH 或 ALPHA;请使用 ALPHA_SCISSOR,以提升性能并改善排序。
  25. 绝对不要缩放 CollisionShape 节点(Node2D/3D 缩放)——使用形状手柄或调整资源大小,避免出现不可预测的物理法线和抖动。
  26. 当 is_on_floor() 为 true 时,绝对不要施加重力——这会导致微抖动并妨碍贴地。务必将垂直速度重置为 0 或一个较小的常数。
  27. 绝对不要忘记断开动态信号(捕获 Lambda)——Godot 无法自动断开捕获局部变量的 Lambda;它们会导致已释放对象发生崩溃。
  28. 绝对不要在移动设备上使用鼠标事件处理触控——务必使用 InputEventScreenTouch 和 InputEventScreenDrag,以可靠地支持多点触控。
  29. 绝对不要在移动设备上使用 Forward+ 渲染器——务必使用 Mobile 或 Compatibility 渲染器,避免 GPU 瓶颈和电量消耗。
  30. 绝对不要将鼠标旋转直接累加到变换上——务必单独存储 Yaw/Pitch 变量,以避免万向节死锁和精度损失。
  31. 绝对不要在高频运行时检查中使用普通字符串——务必使用 StringName(&"active"),以避免 O(n) 哈希开销。
  32. 绝对不要信任客户端提供的游戏状态(Health、Inventory)——客户端只提出操作建议,由服务器验证并广播,以防作弊。
  33. 绝对不要在移动更新中使用 Reliable RPC——请使用 UnreliableOrdered,以避免高延迟场景下的队首阻塞。

📊 第 5 部分:性能预算(具体数值)

指标移动端目标桌面端目标专家说明
绘制调用< 100(2D),< 200(3D)< 500使用 MultiMeshInstance 处理植被/碎片
三角形数量< 100K 可见< 1M 可见超过 500K 时必须使用 LOD 系统
纹理 VRAM< 512MB< 2GBVRAM 压缩:ETC2(移动端),BPTC(桌面端)
脚本耗时每帧 < 4ms每帧 < 8ms将热点循环移至 Server API
物理体< 200 个活动物理体< 1000 个活动物理体大规模模拟时使用 PhysicsServer 直接 API
粒子< 2000 个< 10000 个使用 GPU 粒子,手动设置 visibility_aabb
音频总线< 8 个同时运行< 32 个同时运行使用 音频系统 总线路由
存档文件大小< 1MB< 50MB程序化世界使用种子 + 增量模式
场景加载时间< 500ms< 2sResourceLoader.load_threaded_request()

⚙️ 第 6 部分:Server API — 专家级性能逃生舱

这是大多数 Godot 开发者永远不会了解的知识。当场景树成为瓶颈时,可使用 Godot 的底层 Server API 完全绕过它。

何时改用 Server API
  • 渲染实例超过 10K(精灵、网格):使用带 RID 的 RenderingServer,而不是 Sprite2D/MeshInstance3D 节点。
  • 弹幕游戏 / 粒子系统需要脚本交互时:使用 PhysicsServer2D 创建物理体,而不是 Area2D 节点。
  • 大规模物理模拟:直接使用 PhysicsServer3D,用于布娃娃场、碎片或类流体模拟。
📊 性能对比:SceneTree 与 Server API

绕过 SceneTree 可以消除节点生命周期管理、信号传播和虚函数(如 _process)带来的大量 CPU 开销。

指标SceneTree(节点)Server API(RID)专家说明
对象上限~1,000 - 5,00050,000+SceneTree 遍历开销为 O(n);Server 使用 O(1) 直接 RID 句柄。
内存开销每个节点约 2KB - 10KB每个 RID < 200 bytes节点包含树状态、信号和检查器元数据。RID 是不透明的 24-byte 句柄。
CPU 耗时高(虚调用)极低(直接 API)每个节点实例都必须调用 _process。Server 会在 C++ 中批处理操作。
线程处理仅主线程天然线程安全大多数 Server API 都是线程安全的(必须在 Project Settings 中启用)。
垃圾回收自动(RefCounted)手动(分配/释放)Server 需要手动管理生命周期(创建/删除 RID)。

专家说明:使用 RID 可以管理原始数据并直接与引擎核心逻辑交互。这是弹幕游戏、大规模植被或复杂程序化模拟的主要“逃生舱”,适用于 SceneTree 的维护工作成为瓶颈的情况。

RID 模式(专家级)

Server API 通过 RID(资源 ID)通信——它是服务器端对象的不透明句柄。关键规则:

# Create server-side canvas item (NO node overhead)
var ci_rid := RenderingServer.canvas_item_create()
RenderingServer.canvas_item_set_parent(ci_rid, get_canvas_item())

# CRITICAL: Keep resource references alive. RIDs don't count as references.
# If the Texture resource is GC'd, the RID becomes invalid silently.
var texture: Texture2D = preload("res://sprite.png")
RenderingServer.canvas_item_add_texture_rect(ci_rid, Rect2(-texture.get_size() / 2, texture.get_size()), texture)
使用 Server API 进行线程处理
  • 场景树不是线程安全的。但在 Project Settings 中启用后,Server API(RenderingServer、PhysicsServer)是线程安全的。
  • 可以在工作线程上构建场景块(实例化 + add_child),但必须使用 add_child.call_deferred() 将其附加到活动场景树。
  • GDScript Dictionary/Array:跨线程读写是安全的,但调整大小(append、erase、resize)需要使用 Mutex。
  • 绝不要同时从多个线程加载同一个 Resource——请使用一个加载线程。

🧩 第 7 部分:专家级代码模式

常见架构与游戏玩法系统的专家级实现。


🔥 第 8 部分:Godot 4.x 易踩坑点(仅供资深用户)

  1. @export 资源默认会共享:多个场景实例会共享同一个 Resource。在 _ready() 中使用 resource.duplicate(),或启用“Local to Scene”(场景局部)复选框。这是新手报告最多的 Godot 4 问题。
  2. 信号语法会静默失效:connect("signal_name", target, "method")(Godot 3 语法)虽然能通过编译,但在 Godot 4 中不起作用。必须使用 signal_name.connect(callable)。
  3. Tween 不再是 Node:通过 create_tween() 创建,并绑定到创建节点的生命周期。如果该节点被释放,Tween 也会随之销毁。要创建持久补间,请使用 get_tree().create_tween()。
  4. PhysicsBody 的图层与遮罩:collision_layer =“我是什么”。collision_mask =“我要扫描什么”。将两者设置为相同的值会导致自碰撞或漏检。
  5. 高频路径中的 StringName 与 String:StringName(&"key")使用指针比较(O(1))。String 使用字符比较(O(n))。_process 中的字典键始终使用 StringName。
  6. @onready 的时机:在 _init() 之后、_ready() 期间运行。如果需要在构造时进行设置,请使用 _init()。如果需要访问场景树,请使用 @onready 或 _ready()。混用会导致空值。
  7. 服务器查询会造成卡顿:在 _process 中调用 RenderingServer 或 PhysicsServer 的 getter 函数会强制同步刷新管线。这些服务器以异步方式运行,从它们请求数据会导致整个管线停顿,直到服务器追上进度。
  8. move_and_slide() API 变更:返回 bool(是否发生碰撞)。velocity 现在是属性,而非参数。调用 move_and_slide() 前,先执行 velocity = dir * speed。

📂 第 9 部分:模块目录(100 个蓝图)

重要

仅加载当前工作流所需的模块。使用第 2 部分中的决策矩阵确定要遵循的链路。

架构与基础

基础 | 组合 | 应用组合 | 信号 | 自动加载 | 状态 | 资源 | 模板 | 分析员 | 审计员 | 构建器 | GDAS-reader | REA

版本升级(外部中心): godot-version-migration — 完整历史路由器(旧版本时期、3→4 桥接、4.0→4.7 跳转);此处未镜像该内容。

GDScript & Testing

GDScript Mastery | Testing Patterns | Debugging/Profiling | Performance Optimization

2D Systems

2D Animation | 2D Physics | Tilemaps | Animation Player | Animation Tree | CharacterBody2D | Particles | Tweening | Shader Basics | Camera Systems

3D Systems

3D Lighting | 3D Materials | 3D World Building | Physics 3D | Navigation/Pathfinding | Procedural Generation | Raycasting

Gameplay Mechanics

Abilities | Combat | Dialogue | Economy | Inventory | Questing | RPG Stats | Turn System | Audio | Scene Transitions | Save/Load | Secrets | Collections | Waves | Harvesting | Time Trials | Revival | Monte Carlo Balancer

UI & UX

UI Containers | Rich Text | Theming | Input Handling | Seasonal Theming | Agent Vision

Connectivity & Platforms

Multiplayer | Server Logic | Export Builds | Desktop | Mobile | Web | Console | VR

Adaptation Guides
类型蓝图(完整)

动作角色扮演 | 射击游戏 | 第一人称射击游戏 | 即时战略 | 多人在线战术竞技游戏 | Rogue-like | 生存游戏 | 开放世界 | 类银河战士恶魔城 | 平台游戏 | 格斗游戏 | 潜行游戏 | 沙盒游戏 | 恐怖游戏 | 解谜游戏 | 竞速游戏 | 节奏游戏 | 体育游戏 | 大逃杀 | 卡牌游戏 | 视觉小说 | 恋爱游戏 | 模拟游戏 | 塔防游戏 | 放置点击游戏 | 派对游戏 | 教育游戏


🐛 第 10 部分:专家级诊断模式

“不可见节点”错误

症状:节点存在于树中,但没有渲染。 专家诊断链:visible 属性 → z_index → 父级 CanvasLayer 图层错误 → modulate.a == 0 → 位于摄像机 near 裁剪面之后(3D)→ 未设置 SubViewport.render_target_update_mode → CanvasItem 不在任何 CanvasLayer 中(渲染在所有内容之后)。

“输入被吞掉”错误

症状:点击或按键间歇性地被忽略。 专家诊断:另一个 Control 节点的 mouse_filter = STOP,与目标重叠。或者,模态 PopupMenu 正在消耗未处理的输入。或者,另一个脚本中的 _unhandled_input() 调用了 get_viewport().set_input_as_handled()。

“物理抖动”错误

症状:角色在与表面接触时振动。 专家诊断:Safe Margin 过大。或者,使用 _process 而不是 _physics_process 移动(插值不匹配)。或者,生成时碰撞形状重叠(导致它们永久地相互推开)。

“内存泄漏”

症状:游戏运行时 RAM 持续增长。 专家诊断:调用了 queue_free(),但 Array/Dictionary 中仍保留着引用。或者,信号使用 CONNECT_REFERENCE_COUNTED 连接,却没有清理。使用 Profiler 的 “Objects” 选项卡查找孤立实例。搜索没有父级的 Node 实例。

“帧率骤降”

症状:FPS 平稳,但会周期性下降。 专家诊断:GDScript GC 扫描。或者,对大型资源进行同步 load()。或者,NavigationServer 重新烘焙。或者,Server API 查询停顿(在 _process 中向 RenderingServer 请求数据)。使用内置 Profiler 进行分析 → 查找函数级别的尖峰。


🚀 第 11 部分:快速入门 — 从 Unity(C#)到 Godot(GDScript)

从 Unity 生态系统转型的资深工程师需要调整的思维模型。

1. 节点与 GameObject 和组件

在 Unity 中,GameObject 是 Components 的容器。在 Godot 中,一切都是节点。

  • Unity:GameObject + Transform + MeshFilter + Script。
  • Godot:一个 MeshInstance3D 节点(它本身就是一个 Transform 和 Mesh),并附加一个脚本。
  • 专家思维转变:使用节点组合。如果需要“生命值组件”,就添加一个名为 “Health” 的 Node 或 Area3D 作为子节点。对于仅包含逻辑的组件,使用 RefCounted 以节省内存。
2. 场景是嵌套的预制体

Godot 没有“预制体”,因为每个场景都是一个预制体。

  • 可以在一个场景中实例化另一个场景,层层嵌套,深不见底。
  • 专家思维转变:每个可复用系统(玩家、敌人、UI 按钮)都应该有自己的 .tscn 文件。这有助于实现“后序遍历”(子节点会先于父节点就绪)。
3. 信号与事件/操作

Godot 的 Signal 系统是观察者模式的原生实现。

  • Unity:event Action OnDeath;。
  • Godot:signal died。
  • 专家思路转变:信号是一等公民。它们会显示在检查器中,并且可以动态连接或通过编辑器连接。对于全局事件,使用“信号总线”模式(Autoload),以模拟 Unity 的单例管理器。
4. 脚本作为类扩展

将脚本附加到节点时,该脚本就是该节点。

  • Unity:GetComponent<MyScript>()。
  • Godot:脚本会扩展节点的类(例如,extends CharacterBody3D)。
  • 专家思路转变:使用类型化 GDScript(var x: int = 5),以提升编译速度并获得编辑器补全。编译时已知类型的情况下,类型化 GDScript 会使用经过优化的操作码。
5. 内存管理:没有垃圾回收停顿

与可能出现“GC 峰值”的 Unity C# 不同,GDScript 使用引用计数。

  • 专家思路转变:对象一旦不再被引用,就会立即释放。这带来确定性的性能,并避免大型 Unity 项目中常见的间歇性“卡顿”。
6. StringNames 与性能

Unity 使用 int 或 Enum 来提升性能。Godot 使用 StringName。

  • 专家思路转变:使用 &"name",在字典查找和信号查找中进行常数时间(O(1))的指针比较。

参考资料

评论

支持 Markdown