godot-master

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Godot Master: Lead Architect Knowledge Hub

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

Every section earns its tokens by focusing on Knowledge Delta — the gap between what the base model already knows and what a senior Godot engineer knows from shipping real products.
每个章节都通过聚焦 **Knowledge Delta(知识增量)**来证明其 token 价值——即基础模型已知内容与资深 Godot 工程师通过交付真实产品所掌握知识之间的差距。

Library target — Godot 4.7+

知识库目标——Godot 4.7+

All Domain Skill mirrors target Godot 4.7+ (stable). For any engine version upgrade (1.x/2.x legacy → 3→4 → hop-by-hop 4.x), use godot-version-migration — do not treat this hub as a migration changelog.
Cross-cutting 4.7 reminders while routing: AreaLight3D / HDR → 3D Lighting; Asset Store vs Asset Library → export/platform modules; RichTextLabel ImageUnit, input device ID constants, Jolt behavior → migration hub module notes.

所有 Domain Skill 镜像均以 Godot 4.7+(稳定版)为目标。对于任何引擎版本升级(1.x/2.x 旧版 → 3 → 4 → 逐版本升级 4.x),请使用 godot-version-migration——不要将本中心视为迁移变更日志。
路由时需要牢记的 4.7 跨领域提醒:AreaLight3D / HDR → 3D Lighting;Asset Store 与 Asset Library 的区别 → 导出/平台模块;RichTextLabel ImageUnit、输入设备 ID 常量、Jolt 行为 → 迁移中心模块说明。

🧠 Part 1: Expert Thinking Frameworks

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

"Who Owns What?" — The Architecture Sanity Check

“谁拥有什么?”——架构合理性检查

Before writing any system, answer these three questions for EVERY piece of state:
  • Who owns the data? (The
    StatsComponent
    owns health, NOT the
    CombatSystem
    )
  • Who is allowed to change it? (Only the owner via a public method like
    apply_damage()
    )
  • Who needs to know it changed? (Anyone listening to the
    health_changed
    signal)
If you can't answer all three for every state variable, your architecture has a coupling problem. This is not OOP encapsulation — this is Godot-specific because the signal system IS the enforcement mechanism, not access modifiers.
在编写任何系统之前,针对每一份状态回答以下三个问题:
  • 谁拥有数据?(
    StatsComponent
    拥有生命值,而不是
    CombatSystem
    )
  • 谁有权修改它?(仅所有者可通过
    apply_damage()
    等公共方法修改)
  • 谁需要知道它发生了变化?(任何监听
    health_changed
    signal 的对象)
如果无法为每个状态变量回答这三个问题,你的架构就存在耦合问题。这并非普通的 OOP 封装问题——它是 Godot 特有的,因为 signal 系统才是约束机制,而不是访问修饰符。

The Godot "Layer Cake"

Godot“分层蛋糕”

Organize every feature into four layers. Signals travel UP, never down:
┌──────────────────────────────┐
│  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
└──────────────────────────────┘
Critical rule: Presentation MUST NOT modify Data directly. Infrastructure speaks exclusively through signals. If a
Label
node is calling
player.health -= 1
, the architecture is broken.
将每个功能组织为四层。Signal 只能向上传递,绝不能向下传递:
┌──────────────────────────────┐
│  PRESENTATION(表现层:UI / VFX)  │  ← 监听 signal,绝不拥有数据
├──────────────────────────────┤
│  LOGIC(逻辑层:状态机)          │  ← 编排转换并查询数据
├──────────────────────────────┤
│  DATA(数据层:Resources / .tres) │  ← 单一事实来源,可序列化
├──────────────────────────────┤
│  INFRASTRUCTURE(基础设施层)      │  ← Signal Bus、SaveManager、AudioBus
└──────────────────────────────┘
关键规则:PRESENTATION 绝不能直接修改 DATA。INFRASTRUCTURE 只能通过 signal 通信。如果
Label
节点正在执行
player.health -= 1
,则架构已经失效。

The Signal Bus Tiered Architecture

分层 Signal Bus 架构

  • Global Bus (Autoload): ONLY for lifecycle events (
    match_started
    ,
    player_died
    ,
    settings_changed
    ). Debugging sprawl is the cost — limit events to < 15.
  • Scoped Feature Bus: Each feature folder has its own bus (e.g.,
    CombatBus
    only for combat nodes). This is the compromise that scales.
  • Direct Signals: Parent-child communication WITHIN a single scene. Never across scene boundaries.
  • Global Bus(Autoload):仅用于生命周期事件(
    match_started
    、
    player_died
    、
    settings_changed
    )。代价是调试代码蔓延——应将事件限制在 15 个以内。
  • Scoped Feature Bus:每个功能目录拥有自己的 bus(例如
    CombatBus
    仅服务于战斗节点)。这是可扩展的折中方案。
  • Direct Signals:用于单个场景内部的父子通信。绝不用于跨场景边界通信。

🔗 The "Smart Interconnect" Mandate

🔗 “智能互联”原则

Expert systems are defined not by their isolation, but by their Payload Synthesis.
  • Physics → Performance:
    PhysicsServer2D
    and
    RenderingServer
    bypass
    SceneTree
    node overhead. Use for 1,000+ bullets or particles to achieve O(1) processing.
  • Animation → Physics:
    AnimationTree.get_root_motion_position()
    converts animation displacement into physics
    velocity
    , preventing "foot sliding" in complex movement.
  • Data → Reactivity: Serialized
    Resource
    objects (like
    Stats
    ) emit signals when modified, allowing UI to update automatically without tight coupling.
  • Asset → Spawning: An O(1) Dictionary-based cache (preloaded during
    ResourceLoader
    async phases) prevents I/O hitches when spawning items or enemies.
  • Mobile → Visuals: Prevent runtime frame-hitches by instantiating hidden effects during loading screens to force GPU shader pipeline compilation.
  • Networking → Bandwidth: Use bit-packing into
    PackedByteArray
    for synchronization instead of JSON/Strings to keep packets under 100 bytes.
  • Genre Synthesis:
    • Shooter
      : strictly use
      intersect_ray()
      (direct space state) over
      RayCast3D
      nodes for 100x performance.
    • RPG
      : Damage follows
      base * pow(scaling, level)
      to sustain end-game progression.
    • RTS
      : Moves groups based on their Center of Mass with
      Relative Offset
      to preserve formation integrity.
    • Metroidvania
      : Uses
      ResourceLoader.load_threaded_request()
      for seamless room swaps.
    • Platformer
      : Mandatory
      Jump Buffering
      (~0.15s) and
      Coyote Time
      for professional feel.
    • Simulation
      :
      Tick Manager
      batch processing; avoid per-entity
      _process
      to sustain thousands of units.
    • Romance
      :
      Multi-Axial Affection
      (Attraction, Trust, Comfort) to map complex narrative branching.
    • Architecture
      :
      Signal Architecture
      strictly follows
      Signal Up, Call Down
      to eliminate circular scene coupling.

专家系统的关键不在于隔离,而在于 Payload Synthesis(载荷综合)。
  • Physics → Performance:
    PhysicsServer2D
    和
    RenderingServer
    可绕过
    SceneTree
    的节点开销。对于 1,000+ 子弹或粒子,使用它们可实现 O(1) 处理。
  • Animation → Physics:
    AnimationTree.get_root_motion_position()
    可将动画位移转换为物理
    velocity
    ,避免复杂移动中的“脚滑”。
  • Data → Reactivity:序列化后的
    Resource
    对象(例如
    Stats
    )在修改时发出 signal,使 UI 可自动更新且不会形成紧密耦合。
  • Asset → Spawning:基于
    Dictionary
    的 O(1) 缓存(在
    ResourceLoader
    异步阶段预加载)可避免生成物品或敌人时发生 I/O 卡顿。
  • Mobile → Visuals:在加载画面期间实例化隐藏特效,强制完成 GPU shader pipeline 编译,从而防止运行时帧卡顿。
  • Networking → Bandwidth:同步时使用
    PackedByteArray
    进行位打包,而非 JSON/Strings,从而将数据包控制在 100 bytes 以内。
  • 类型综合:
    • Shooter
      (射击游戏):严格使用
      intersect_ray()
      (直接空间状态),而非
      RayCast3D
      节点,性能可提升 100 倍。
    • RPG
      :伤害采用
      base * pow(scaling, level)
      ,以维持终局阶段的成长性。
    • RTS
      :根据群体的 Center of Mass 移动,并使用
      Relative Offset
      保持阵型完整性。
    • Metroidvania
      :使用
      ResourceLoader.load_threaded_request()
      实现无缝房间切换。
    • Platformer
      :必须实现
      Jump Buffering
      (约 0.15 秒)和
      Coyote Time
      ,以获得专业级操作手感。
    • Simulation
      :使用
      Tick Manager
      批处理;避免对每个实体调用
      _process
      ,以维持数千单位同时运行。
    • Romance
      :采用
      Multi-Axial Affection
      (Attraction、Trust、Comfort)映射复杂的叙事分支。
    • Architecture
      :
      Signal Architecture
      严格遵循“Signal 向上、调用向下”,从而消除循环场景耦合。

🧭 Part 2: Architectural Decision Frameworks

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

The Master Decision Matrix

首席决策矩阵

ScenarioStrategyMANDATORY Skill ChainTrade-off
Rapid PrototypeEvent-Driven MonoREAD: Foundations → Autoloads. Do NOT load genre or platform refs.Fast start, spaghetti risk
Complex RPGComponent-DrivenREAD: Composition → States → RPG Stats. Do NOT load multiplayer or platform refs.Heavy setup, infinite scaling
Massive Open WorldResource-StreamingREAD: Open World → Save/Load. Also load Performance.Complex I/O, float precision jitter past 10K units
Server-Auth MultiDeterministicREAD: Server Arch → Multiplayer. Do NOT load single-player genre refs.High latency, anti-cheat secure
Mobile/Web PortAdaptive-ResponsiveREAD: UI Containers → Adapt Desk→Mobile → Platform Mobile.UI complexity, broad reach
Application / ToolApp-CompositionREAD: App Composition → Theming. Do NOT load game-specific refs.Different paradigm than games
Romance / Dating SimAffection EconomyREAD: Romance → Dialogue → UI Rich Text.High UI/Narrative density
Secrets / Easter EggsIntentional ObfuscationREAD: Secrets → Persistence.Community engagement, debug risk
Collection QuestScavenger LogicREAD: Collections → Marker3D Placement.Player retention, exploration drive
Seasonal EventRuntime InjectionREAD: Easter Theming → Material Swapping.Fast branding, no asset pollution
Souls-like MortalityRisk-Reward RevivalREAD: Revival/Corpse Run → Physics 3D.High tension, player frustration risk
Wave-based ActionCombat Pacing LoopREAD: Waves → Combat.Escalating tension, encounter design
Balance / Difficulty / Economy PacingMonte Carlo Balance LabREAD: Resources → Economy → Combat / RPG Stats / Waves (as needed) → Monte Carlo Balancer → Testing → Builder.Statistical rigor; abstract sim must calibrate vs headless Godot
Survival EconomyHarvesting LoopREAD: Harvesting → Inventory.Resource scarcity, loop persistence
Racing / SpeedrunValidation LoopREAD: Time Trials → Input Buffer → Genre Racing.High precision, ghost record drive
Horror / StealthTension ManagementREAD: Genre Horror → Genre Stealth → Audio.Atmosphere, player vulnerability
Card / Board GameRule EnforcementREAD: Genre Card Game → Turn System.Deterministic state, UI heavy
Simulation / RTSBatch ProcessingREAD: Genre Simulation → Genre RTS → Performance.High unit counts, O(1) logic
HDR / Cinematic VisualsDisplay PipelineREAD: 3D Lighting → Platform Desktop → Shaders. Enable viewport HDR in Project Settings.Platform-specific tonemapping tuning
Rectangular Area LightsAreaLight3DREAD: 3D Lighting → 3D Materials. Prefer AreaLight3D over emissive+GI hacks.Forward+ renderer required for full quality
Mobile Touch ControlsNative JoystickREAD: Platform Mobile → Adapt Desk→Mobile. Use built-in virtual joystick (4.7+).Less plugin dependency
Addon / Asset DiscoveryAsset StoreREAD: Project Foundations → Export Builds. Asset Store replaces Asset Library.Beta store UI — verify licensing per addon
Agent Eyes / Visual QACapture → WebP → RubricREAD: Agent Vision. Screenshot assets, window/region/screen, or TEMP editor bridge — then structured review. Do NOT load genre refs.Host-side only; never Autoload / never leave staged addon
场景策略必选 Skill 链权衡
快速原型Event-Driven Mono读取:Foundations → Autoloads。不要加载类型或平台参考文档。启动快,但存在意大利面式代码风险
复杂 RPGComponent-Driven读取:Composition → States → RPG Stats。不要加载多人游戏或平台参考文档。设置较重,可无限扩展
大型开放世界Resource-Streaming读取:Open World → Save/Load。同时加载 Performance。I/O 复杂;超过 10K 单位后会出现浮点精度抖动
服务器权威多人游戏Deterministic读取:Server Arch → Multiplayer。不要加载单人类型参考文档。延迟较高,但抗作弊安全性更高
移动端/Web 移植Adaptive-Responsive读取:UI Containers → Adapt Desk→Mobile → Platform Mobile。UI 复杂,但覆盖范围广
应用/工具App-Composition读取:App Composition → Theming。不要加载游戏专用参考文档。与游戏相比属于不同范式
恋爱/约会模拟Affection Economy读取:Romance → Dialogue → UI Rich Text。UI/叙事密度高
秘密/彩蛋Intentional Obfuscation读取:Secrets → Persistence。有利于社区参与,但存在调试风险
收集任务Scavenger Logic读取:Collections → Marker3D Placement。提升玩家留存并推动探索
季节性活动Runtime Injection读取:Easter Theming → Material Swapping。品牌更新快,不会污染正式资源
类魂系死亡机制Risk-Reward Revival读取:Revival/Corpse Run → Physics 3D。张力高,但可能令玩家受挫
波次制动作游戏Combat Pacing Loop读取:Waves → Combat。逐步提升紧张感并优化战斗遭遇设计
平衡性/难度/经济节奏Monte Carlo Balance Lab读取:Resources → Economy → Combat / RPG Stats / Waves(按需)→ Monte Carlo Balancer → Testing → Builder。具有统计严谨性;抽象模拟必须针对 headless Godot 进行校准
生存经济Harvesting Loop读取:Harvesting → Inventory。资源稀缺,循环具有持久性
竞速/速通Validation Loop读取:Time Trials → Input Buffer → Genre Racing。精度要求高,可推动幽灵录像功能
恐怖/潜行Tension Management读取:Genre Horror → Genre Stealth → Audio。营造氛围,增强玩家脆弱感
卡牌/棋盘游戏Rule Enforcement读取:Genre Card Game → Turn System。状态确定,UI 较重
模拟/RTSBatch Processing读取:Genre Simulation → Genre RTS → Performance。支持大量单位,逻辑复杂度为 O(1)
HDR/电影级视觉效果Display Pipeline读取:3D Lighting → Platform Desktop → Shaders。在 Project Settings 中启用 viewport HDR。需要针对平台调整 tonemapping
矩形区域光AreaLight3D读取:3D Lighting → 3D Materials。优先使用 AreaLight3D,而非 emissive+GI 技巧。完整质量需要 Forward+ renderer
移动端触控控制Native Joystick读取:Platform Mobile → Adapt Desk→Mobile。使用内置虚拟摇杆(4.7+)。减少插件依赖
Addon/资源发现Asset Store读取:Project Foundations → Export Builds。Asset Store 取代 Asset Library。商店 UI 处于 Beta;必须逐个核实 addon 许可
Agent Eyes/视觉 QACapture → WebP → Rubric读取:Agent Vision。截取屏幕、窗口/区域/屏幕资源,或使用 TEMP editor bridge,然后进行结构化审查。不要加载类型参考文档。仅限 Host 端;绝不作为 Autoload,也不得遗留暂存 addon

The "When NOT to Use a Node" Decision

“何时不应使用 Node”决策

One of the most impactful expert-only decisions. The Godot docs explicitly say "avoid using nodes for everything":
TypeWhen to UseCostExpert Use Case
Object
Custom data structures, manual memory managementLightest. Must call
.free()
manually.
Custom spatial hash maps, ECS-like data stores
RefCounted
Transient data packets, logic objects that auto-deleteAuto-deleted when no refs remain.
DamageRequest
,
PathQuery
,
AbilityEffect
— logic packets that don't need the scene tree
Resource
Serializable data with Inspector supportSlightly heavier than RefCounted. Handles
.tres
I/O.
ItemData
,
EnemyStats
,
DialogueLine
— any data a designer should edit in Inspector
Node
Needs
_process
/
_physics_process
, needs to live in the scene tree
Heaviest — SceneTree overhead per node.Only for entities that need per-frame updates or spatial transforms
The expert pattern: Use
RefCounted
subclasses for all logic packets and data containers. Reserve
Node
for things that must exist in the spatial tree. This halves scene tree overhead for complex systems.

这是影响最大的专家级决策之一。Godot 文档明确指出应“避免将 Node 用于一切”:
类型使用时机成本专家用例
Object
自定义数据结构、手动内存管理最轻量。必须手动调用
.free()
。
自定义 spatial hash map、类 ECS 数据存储
RefCounted
临时数据包、无引用后自动删除的逻辑对象无引用后自动删除。
DamageRequest
、
PathQuery
、
AbilityEffect
——无需进入场景树的逻辑数据包
Resource
可序列化且支持 Inspector 的数据略重于 RefCounted。支持
.tres
I/O。
ItemData
、
EnemyStats
、
DialogueLine
——任何应由设计师在 Inspector 中编辑的数据
Node
需要
_process
/
_physics_process
,或必须存在于场景树中
最重——每个节点都有 SceneTree 开销。仅用于需要逐帧更新或空间变换的实体
专家模式:所有逻辑数据包和数据容器都使用
RefCounted
子类。仅将
Node
保留给必须存在于空间树中的对象。这可使复杂系统的场景树开销减半。

🔧 Part 3: Core Workflows

🔧 第 3 部分:核心工作流

Workflow 1: Professional Scaffolding

工作流 1:专业脚手架

From empty project to production-ready container.
MANDATORY — READ ENTIRE FILE: Foundations
  1. Organize by Feature (
    /features/player/
    ,
    /features/combat/
    ), not by class type. A
    player/
    folder contains the scene, script, resources, and tests for the player.
  2. READ: Signal Architecture — Create
    GlobalSignalBus
    autoload with < 15 events.
  3. READ: GDScript Mastery — Enable
    untyped_declaration
    warning in Project Settings → GDScript → Debugging.
  4. Apply Project Templates for base
    .gitignore
    , export presets, and input map.
  5. Use Builder (
    create_scene.py
    ,
    add_node.py
    ,
    save_scene.py
    ) to generate scene hierarchies programmatically via the Godot CLI.
[!CAUTION] Workflow 1 NEVER List
  • NEVER use
    res://
    paths in logic scripts. Use
    @export_file
    or
    @export_dir
    to ensure resources remain valid when moved.
  • NEVER initialize children in
    _init()
    . The scene tree isn't ready. Use
    _ready()
    or
    @onready
    .
  • NEVER keep "Default" project settings for
    Physics Ticks
    . Set to 60 for consistency, or use
    Engine.physics_ticks_per_second
    for adaptive logic.
  • NEVER use
    print()
    in
    _process()
    for debugging; use the
    Debugger
    or
    push_error()
    to avoid frame-time spikes.
Do NOT load combat, multiplayer, genre, or platform references during scaffolding.
从空项目到可用于生产的项目容器。
必须完整读取:Foundations
  1. 按功能组织项目(
    /features/player/
    、
    /features/combat/
    ),而不是按类类型组织。
    player/
    目录应包含 Player 的场景、脚本、资源和测试。
  2. 读取:Signal Architecture——创建包含少于 15 个事件的
    GlobalSignalBus
    Autoload。
  3. 读取:GDScript Mastery——在 Project Settings → GDScript → Debugging 中启用
    untyped_declaration
    警告。
  4. 应用 Project Templates,生成基础
    .gitignore
    、导出预设和输入映射。
  5. 使用 Builder(
    create_scene.py
    、
    add_node.py
    、
    save_scene.py
    ),通过 Godot CLI 以程序方式生成场景层级。
[!CAUTION] 工作流 1 禁止事项
  • 逻辑脚本中绝不使用
    res://
    路径。使用
    @export_file
    或
    @export_dir
    ,确保资源移动后仍然有效。
  • 绝不在
    _init()
    中初始化子节点。此时场景树尚未就绪,应使用
    _ready()
    或
    @onready
    。
  • 绝不保留“Default”项目的
    Physics Ticks
    设置。将其设为 60 以保持一致,或使用
    Engine.physics_ticks_per_second
    实现自适应逻辑。
  • 绝不在
    _process()
    中使用
    print()
    调试;使用
    Debugger
    或
    push_error()
    ,避免帧时间峰值。
搭建脚手架期间,不要加载战斗、多人游戏、类型或平台参考文档。

Workflow 2: Entity Orchestration

工作流 2:实体编排

Building modular, testable characters.
MANDATORY Chain — READ ALL: Composition → State Machine → CharacterBody2D or Physics 3D → Animation Tree Do NOT load UI, Audio, or Save/Load references for entity work.
  • The State Machine queries an
    InputComponent
    , never handles input directly. This allows AI/Player swap with zero refactoring.
  • The State Machine ONLY handles transitions. Logic belongs in Components.
    MoveState
    tells
    MoveComponent
    to act, not the other way around.
  • Every entity MUST pass the F6 test: pressing "Run Current Scene" (F6) must work without crashing. If it crashes, your entity has scene-external dependencies.
[!CAUTION] Workflow 2 NEVER List
  • NEVER call
    parent.do_thing()
    . If the parent changes, the entity breaks. Emit a signal
    request_action
    instead.
  • NEVER use
    _process
    for movement. Use
    _physics_process
    to avoid jitter on variable-refresh-rate monitors.
  • NEVER hardcode animation names. Use a
    StringName
    constant or a
    Resource
    map to enable easy renaming in
    AnimationPlayer
    .
  • NEVER use
    get_node()
    with absolute paths. Use
    %UniqueName
    to survive tree refactoring.
构建模块化、可测试的角色。
必须完整读取:Composition → State Machine → CharacterBody2D 或 Physics 3D → Animation Tree 实体开发期间,不要加载 UI、Audio 或 Save/Load 参考文档。
  • State Machine 应查询
    InputComponent
    ,而绝不直接处理输入。这样可以在无需重构的情况下切换 AI/Player。
  • State Machine 只负责状态转换。逻辑属于 Components。
    MoveState
    指示
    MoveComponent
    执行动作,而不是反过来。
  • 每个实体都必须通过 F6 测试:按“Run Current Scene”(F6)时不得崩溃。如果崩溃,说明实体存在场景外依赖。
[!CAUTION] 工作流 2 禁止事项
  • 绝不调用
    parent.do_thing()
    。如果父节点发生变化,实体就会失效。应发出
    request_action
    signal。
  • 绝不使用
    _process
    进行移动。使用
    _physics_process
    ,避免可变刷新率显示器上出现抖动。
  • 绝不硬编码动画名称。使用
    StringName
    常量或
    Resource
    映射,以便轻松重命名
    AnimationPlayer
    中的动画。
  • 绝不使用绝对路径调用
    get_node()
    。使用
    %UniqueName
    ,使其在场景树重构后仍然有效。

Workflow 3: Data-Driven Systems

工作流 3:数据驱动系统

Connecting Combat, Inventory, Stats through Resources.
MANDATORY Chain — READ ALL: Resource Patterns → RPG Stats → Combat → Inventory
  • Create ONE
    ItemData.gd
    extending
    Resource
    . Instantiate it as 100
    .tres
    files instead of 100 scripts.
  • The HUD NEVER references the Player directly. It listens for
    player_health_changed
    on the Signal Bus.
  • Enable "Local to Scene" on ALL
    @export Resource
    variables, or call
    resource.duplicate()
    in
    _ready()
    . Failure to do this is Bug #1 in Part 8.
[!CAUTION] Workflow 3 NEVER List
  • NEVER pass
    Node
    references in a Signal Bus. Objects get freed; RIDs or IDs are safer for long-term tracking.
  • NEVER modify a
    .tres
    file at runtime via code (it modifies the disk file). Always
    .duplicate()
    before modifying.
  • NEVER use
    Array
    for high-frequency search. Use
    Dictionary
    with
    StringName
    keys for O(1) lookups.
  • NEVER use
    float
    for item counts or precise resource tracking; use
    int
    and scale for display.
通过 Resource 连接战斗、背包和属性系统。
必须完整读取:Resource Patterns → RPG Stats → 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。
[!CAUTION] 工作流 3 禁止事项
  • 绝不在 Signal Bus 中传递
    Node
    引用。对象可能被释放;长期跟踪应使用 RID 或 ID。
  • 绝不在运行时通过代码修改
    .tres
    文件,因为这会修改磁盘文件。修改前始终先调用
    .duplicate()
    。
  • 绝不使用
    Array
    执行高频搜索。使用以
    StringName
    为键的
    Dictionary
    ,实现 O(1) 查找。
  • 绝不使用
    float
    表示物品数量或精确资源追踪;使用
    int
    ,并通过缩放进行显示。

Workflow 4: Persistence Pipeline

工作流 4:持久化流水线

MANDATORY: Autoload Architecture → Save/Load → Scene Management
  • Use dictionary-mapped serialization. Old save files MUST not corrupt when new fields are added — use
    .get("key", default_value)
    .
  • For procedural worlds: save the Seed plus a Delta-List of modifications, not the entire map. A 100MB world becomes a 50KB save.
[!CAUTION] Workflow 4 NEVER List
  • NEVER save whole
    Object
    or
    Node
    instances. They contain transient pointers. Extract data into a
    Dictionary
    or custom
    Resource
    .
  • NEVER use
    JSON
    for data that needs strict typing (e.g.,
    Vector2
    ). Use
    var_to_bytes
    or
    ConfigFile
    for structured Godot types.
  • NEVER block the main thread for auto-saves. Use a
    Thread
    or
    WorkerThreadPool
    to serialize large dictionaries.
  • NEVER save to
    res://
    in an exported project; strictly use
    user://
    for persistent data.
必须读取:Autoload Architecture → Save/Load → Scene Management
  • 使用基于字典映射的序列化。添加新字段后,旧存档文件绝不能损坏——使用
    .get("key", default_value)
    。
  • 对于程序化世界:保存 Seed 加修改内容的 Delta-List,而不是保存整张地图。100MB 的世界可压缩为 50KB 的存档。
[!CAUTION] 工作流 4 禁止事项
  • 绝不保存整个
    Object
    或
    Node
    实例。它们包含临时指针。应将数据提取到
    Dictionary
    或自定义
    Resource
    中。
  • 绝不对需要严格类型的数据(例如
    Vector2
    )使用
    JSON
    。使用
    var_to_bytes
    或
    ConfigFile
    处理结构化 Godot 类型。
  • 绝不在主线程上阻塞执行自动保存。使用
    Thread
    或
    WorkerThreadPool
    序列化大型字典。
  • 绝不在导出项目中保存到
    res://
    ;持久化数据必须使用
    user://
    。

Workflow 5: Performance Optimization

工作流 5:性能优化

MANDATORY: Debugging/Profiling → Performance Optimization
Diagnosis-first approach (NEVER optimize blindly):
  1. High Script Time → Profile with built-in Profiler. Check if
    _process
    is being called on hundreds of nodes. Move to single-manager pattern or Server APIs (see Part 6).
  2. High Draw Calls → Use
    MultiMeshInstance
    for repetitive geometry. Batch materials with ORM textures.
  3. Physics Stutter → Simplify collisions to primitive shapes. Load 2D Physics or 3D Physics. Check if
    _process
    is used instead of
    _physics_process
    for movement.
  4. VRAM Overuse → Switch textures to VRAM Compression (BPTC/S3TC for desktop, ETC2 for mobile). Never ship raw PNG.
  5. Intermittent Frame Spikes → Usually GC pass, synchronous
    load()
    , or NavigationServer recalculation. Use
    ResourceLoader.load_threaded_request()
    .
[!CAUTION] Workflow 5 NEVER List
  • NEVER use
    get_nodes_in_group()
    inside
    _process
    . It's an O(n) operation every frame. Cache the array in
    _ready()
    .
  • NEVER use
    Area2D
    signals for "Stay" logic. Use
    get_overlapping_bodies()
    periodically or a manager-level
    PhysicsServer
    check.
  • NEVER optimize before profiling. A 1ms script is irrelevant if you have 2000 draw calls killing the GPU.
  • NEVER use
    load()
    in hot paths; strictly
    preload
    or use
    ResourceLoader
    for async loading.
必须读取:Debugging/Profiling → Performance Optimization
采用诊断优先方式(绝不盲目优化):
  1. 脚本时间过高 → 使用内置 Profiler 进行分析。检查是否对数百个节点调用了
    _process
    。改用单管理器模式或 Server API(参见第 6 部分)。
  2. Draw call 过高 → 对重复几何体使用
    MultiMeshInstance
    。使用 ORM texture 合并材质。
  3. 物理卡顿 → 将碰撞体简化为基础形状。加载 2D Physics 或 3D Physics。检查移动是否错误地使用了
    _process
    而非
    _physics_process
    。
  4. VRAM 使用过多 → 将 texture 切换为 VRAM Compression(桌面端使用 BPTC/S3TC,移动端使用 ETC2)。绝不发布原始 PNG。
  5. 间歇性帧峰值 → 通常由 GC 扫描、同步
    load()
    或 NavigationServer 重算导致。使用
    ResourceLoader.load_threaded_request()
    。
[!CAUTION] 工作流 5 禁止事项
  • 绝不在
    _process
    中调用
    get_nodes_in_group()
    。这是每帧 O(n) 操作,应在
    _ready()
    中缓存数组。
  • 绝不使用
    Area2D
    signal 实现“Stay”逻辑。定期使用
    get_overlapping_bodies()
    ,或在管理器层级使用
    PhysicsServer
    检查。
  • 绝不在分析前进行优化。如果 1ms 的脚本时间无关紧要,但 2000 个 draw call 已经压垮 GPU,则无需关注它。
  • 绝不在热点路径中使用
    load()
    ;严格使用
    preload
    ,或通过
    ResourceLoader
    异步加载。

Workflow 6: Cross-Platform Adaptation

工作流 6:跨平台适配

MANDATORY: Input Handling → Adapt Desktop→Mobile → Platform Mobile Also read: Platform Desktop, Platform Web, Platform Console, Platform VR as needed.
  • Use an
    InputManager
    autoload that translates all input types into normalized actions. NEVER read
    Input.is_key_pressed()
    directly — it blocks controller and touch support.
  • Mobile touch targets: minimum 44px physical size. Use
    MarginContainer
    with Safe Area logic for notch/cutout devices.
  • Web exports: Godot's
    AudioServer
    requires user interaction before first play (browser policy). Handle this with a "Click to Start" screen.
[!CAUTION] Workflow 6 NEVER List
  • NEVER use
    OS.get_name()
    for feature detection. Use
    OS.has_feature("mobile")
    or custom feature tags to handle subsets like "SteamDeck."
  • NEVER assume a specific aspect ratio. Always use
    Expand
    or
    Keep Aspect
    in combinations with
    Anchor
    nodes.
  • NEVER use desktop-only shaders (e.g., complex depth sampling) on Mobile/Web without a GLES3/Compatibility secondary path.
  • NEVER ignore
    physical_keycode
    for desktop builds; it ensures keyboard layouts (AZERTY/QWERTY) don't break movement.
  • NEVER pass unsanitized strings to
    JavaScriptBridge.eval()
    — Prevents script injection in web builds. Use a
    sanitize_js_string()
    helper.
必须读取:Input Handling → Adapt Desktop→Mobile → Platform Mobile 按需读取:Platform Desktop、Platform Web、Platform Console、Platform VR。
  • 使用
    InputManager
    Autoload,将所有输入类型转换为标准化 action。绝不直接读取
    Input.is_key_pressed()
    ,否则会阻碍手柄和触控支持。
  • 移动端触控目标:物理尺寸至少为 44px。在带刘海或挖孔的设备上,使用带 Safe Area 逻辑的
    MarginContainer
    。
  • Web 导出:根据浏览器策略,Godot 的
    AudioServer
    要求首次播放前发生用户交互。通过“Click to Start”画面处理此要求。
[!CAUTION] 工作流 6 禁止事项
  • 绝不使用
    OS.get_name()
    进行功能检测。使用
    OS.has_feature("mobile")
    或自定义 feature tag,以处理
    SteamDeck.
    等子集。
  • 绝不假定特定宽高比。始终将
    Expand
    或
    Keep Aspect
    与
    Anchor
    节点结合使用。
  • 绝不在 Mobile/Web 上使用桌面端专用 shader(例如复杂的 depth sampling),除非提供 GLES3/Compatibility 次要路径。
  • 绝不在桌面端构建中忽略
    physical_keycode
    ;它可确保 AZERTY/QWERTY 等键盘布局不会破坏移动操作。
  • 绝不将未净化的字符串传给
    JavaScriptBridge.eval()
    ,以防止 Web 构建中的脚本注入。使用
    sanitize_js_string()
    辅助函数。

Workflow 7: Procedural Generation

工作流 7:程序化生成

MANDATORY: Procedural Gen → Tilemap Mastery or 3D World Building → Navigation
  • ALWAYS use
    FastNoiseLite
    resource with a fixed
    seed
    for deterministic generation.
  • Never bake NavMesh on the main thread. Use
    NavigationServer3D.parse_source_geometry_data()
    +
    NavigationServer3D.bake_from_source_geometry_data_async()
    .
  • For infinite worlds: chunk loading MUST happen on a background thread using
    WorkerThreadPool
    . Build the scene chunk off-tree, then
    add_child.call_deferred()
    on the main thread.
[!CAUTION] Workflow 7 NEVER List
  • NEVER instantiate nodes for "Background" noise. Use
    MultiMeshInstance
    or draw loops in
    _draw
    for thousands of small details.
  • NEVER regenerate the entire map for one change. Use a "Dirty Chunk" system to only update what exactly changed.
  • NEVER place collisions on the same frame as mesh generation if using
    concave_polygon_shape
    . It stalls the physics thread.
  • NEVER perform pathfinding queries every frame for all units. Use a
    NavigationAgent
    with
    target_position
    updates on a timer.
必须读取:Procedural Gen → Tilemap Mastery 或 3D World Building → Navigation
  • 始终使用带固定
    seed
    的
    FastNoiseLite
    resource,以实现确定性生成。
  • 绝不在主线程上烘焙 NavMesh。使用
    NavigationServer3D.parse_source_geometry_data()
    和
    NavigationServer3D.bake_from_source_geometry_data_async()
    。
  • 对于无限世界:chunk 加载必须通过
    WorkerThreadPool
    在后台线程中执行。在树外构建场景 chunk,然后在主线程上调用
    add_child.call_deferred()
    。
[!CAUTION] 工作流 7 禁止事项
  • 绝不为“Background”噪声实例化节点。对于数千个小细节,使用
    MultiMeshInstance
    或
    _draw
    绘制循环。
  • 绝不因一项更改而重新生成整张地图。使用“Dirty Chunk”系统,仅更新实际发生变化的内容。
  • 使用
    concave_polygon_shape
    时,绝不在与 mesh 生成相同的帧放置碰撞体,否则会阻塞物理线程。
  • 绝不每帧对所有单位执行寻路查询。使用
    NavigationAgent
    ,并通过定时器更新
    target_position
    。

Workflow 8: Multiplayer Architecture

工作流 8:多人游戏架构

MANDATORY — READ: Single→Multiplayer → Networking → Server Arch Do NOT load single-player genre blueprints.
  • Client sends Input, Server calculates Outcome. The Client NEVER determines damage, position deltas, or inventory changes.
  • Use Client-Side Prediction with server reconciliation: predict locally, correct from server snapshot. Hides up to ~150ms of latency.
  • MultiplayerSpawner
    handles replication in Godot 4. Configure it per scene, not globally.
[!CAUTION] Workflow 8 NEVER List
  • NEVER trust
    rpc_id(1, ...)
    (Client to Server) without validation. A hacked client can send
    damage = 999999
    .
  • NEVER replicate
    _process
    transforms directly. Replicate
    Input
    vector and simulate movement on both sides.
  • NEVER use
    TCP
    for high-frequency packets (movement). Use
    UDP
    /
    ENet
    and handle dropped packets with interpolation.
  • NEVER synchronize every projectile; use Client-Side Prediction for visuals and only RPC the "Fire" event.
  • ReflectionProbe
    vs
    VoxelGI
    vs
    SDFGI
    : Probes are cheap/static, VoxelGI is medium/baked, SDFGI is expensive/dynamic. Choose based on your platform budget (see Part 5).
必须读取:Single→Multiplayer → Networking → Server Arch 不要加载单人类型蓝图。
  • Client 发送 Input,Server 计算 Outcome。Client 绝不决定伤害、位置增量或背包变化。
  • 使用带服务器校正的 Client-Side Prediction:在本地预测,再根据服务器快照进行校正。可隐藏最多约 150ms 的延迟。
  • 在 Godot 4 中使用
    MultiplayerSpawner
    处理复制。应按场景而非全局配置它。
[!CAUTION] 工作流 8 禁止事项
  • 绝不在未验证的情况下信任
    rpc_id(1, ...)
    (Client 到 Server)的数据。恶意客户端可以发送
    damage = 999999
    。
  • 绝不直接复制
    _process
    transform。应复制
    Input
    向量,并在双方模拟移动。
  • 绝不对高频数据包(如移动)使用
    TCP
    。使用
    UDP
    /
    ENet
    ,并通过插值处理丢包。
  • 绝不同步每一个 projectile;视觉效果使用 Client-Side Prediction,仅通过 RPC 传递“Fire”事件。
  • ReflectionProbe
    与
    VoxelGI
    、
    SDFGI
    的选择:Probes 成本低且静态,VoxelGI 成本中等且需烘焙,SDFGI 成本高且支持动态效果。应根据平台预算选择(参见第 5 部分)。

Workflow 9: Responsive UI & Expert Theming (Audit Verified)

工作流 9:响应式 UI 与专家主题系统(已通过审计验证)

MANDATORY Chain: UI Containers → UI Theming → Rich Text → Tweening
  1. The F6 Principle: Every UI scene must be testable in isolation. Use
    MOUSE_FILTER_STOP
    only on the background,
    PASS
    on children.
  2. Breathing Room: Use
    add_theme_constant_override("separation", X)
    over manual padding.
  3. Adaptive Scaling: Use
    responsive_layout_builder.gd
    for breakpoint-aware mobile/desktop switching.
  4. Lifecycle Safety: Never scroll to a new child on the same frame.
    await get_tree().process_frame
    before modifying
    scroll_vertical
    .
  5. Data Integration: Use
    Resource-to-UI
    binding; UI nodes MUST be stateless projection layers.
[!CAUTION] Workflow 9 NEVER List
  • NEVER use absolute pixel offsets. UI becomes unreadable on 4K or tiny mobile screens. Use
    Container
    sizing.
  • NEVER deep-nest
    MarginContainers
    . It makes the Inspector unusable. Use a single
    Theme
    resource for project-wide margins.
  • NEVER connect UI buttons to gameplay logic directly. UI sends "Signal",
    PlayerController
    listens. This prevents UI-deletion crashes.
  • NEVER use
    _process()
    to move a UI element to a target. Use a
    Tween
    to avoid stuttering and frame-rate dependence.
  • NEVER leave
    mouse_filter
    as
    STOP
    on transparent containers; it "eats" clicks for everything behind it.
  • NEVER use dynamic
    load()
    on paths without validating the
    res://
    prefix and safe extension (
    .tres
    ,
    .res
    ,
    .theme
    ) — Prevents arbitrary code/resource execution.
必须依次读取:UI Containers → UI Theming → Rich Text → Tweening
  1. F6 原则:每个 UI 场景都必须能够独立测试。仅在背景上使用
    MOUSE_FILTER_STOP
    ,在子节点上使用
    PASS
    。
  2. 留白:使用
    add_theme_constant_override("separation", X)
    ,而不是手动设置 padding。
  3. 自适应缩放:使用
    responsive_layout_builder.gd
    实现基于断点的移动端/桌面端切换。
  4. 生命周期安全:绝不在同一帧滚动到新的子节点。修改
    scroll_vertical
    前先
    await get_tree().process_frame
    。
  5. 数据集成:使用
    Resource-to-UI
    绑定;UI 节点必须是无状态投影层。
[!CAUTION] 工作流 9 禁止事项
  • 绝不使用绝对像素偏移。UI 在 4K 或小型移动屏幕上会变得不可读。应使用
    Container
    调整尺寸。
  • 绝不深层嵌套
    MarginContainer
    ,否则 Inspector 将难以使用。项目范围的 margin 应使用单一
    Theme
    resource 管理。
  • 绝不将 UI 按钮直接连接到游戏逻辑。UI 应发送“Signal”,由
    PlayerController
    监听,从而避免删除 UI 后引发崩溃。
  • 绝不使用
    _process()
    移动 UI 元素。应使用
    Tween
    ,避免卡顿和帧率依赖。
  • 绝不让透明容器的
    mouse_filter
    保持为
    STOP
    ,否则它会“吞掉”后方所有元素的点击。
  • 绝不对未验证
    res://
    前缀及安全扩展名(
    .tres
    、
    .res
    、
    .theme
    )的路径执行动态
    load()
    ,以防止任意代码或 resource 执行。

Workflow 10: Cinematic Lighting & VFX (Audit Verified)

工作流 10:电影级光照与 VFX(已通过审计验证)

MANDATORY Chain: 3D Lighting → Particles → 3D Materials → Shaders
  1. The GI Choice: VoxelGI for interiors, SDFGI for open world. Never ship with both overlapping.
  2. Shadow Budget: Max 2 Shadow-casting DirectionalLights. Use
    fake_gi_bounce.gd
    for mobile fills.
  3. VFX Lifecycle: Use
    finished
    signal over Timers. Re-run with
    restart()
    to avoid async GPU stalls.
  4. Optimization: Use
    ORM Texture
    packing (AO/Rough/Metal) to save GPU cache and texture slots.
  5. Batching: Use
    Instance Uniforms
    for material variations across thousands of instances without draw call penalties.
[!CAUTION] Workflow 10 NEVER List
  • NEVER scale
    CollisionShape
    nodes; strictly scale the Shape Resource to avoid physics jitter.
  • NEVER use
    TRANSPARENCY_ALPHA
    for cutout meshes (leaves/fences); use
    ALPHA_SCISSOR
    to prevent sorting artifacts.
  • NEVER animate CSG nodes during gameplay; forces expensive CPU geometry recalculation.
  • NEVER use real-time Global Illumination (SDFGI/VoxelGI) for a 2D-looking game. Stick to
    DirectionalLight2D
    and
    CanvasModulate
    .
  • NEVER ignore
    Camera3D
    near/far planes; improper settings cause Z-fighting in large worlds.
必须依次读取:3D Lighting → Particles → 3D Materials → Shaders
  1. GI 选择:室内场景使用 VoxelGI,开放世界使用 SDFGI。绝不让二者重叠并同时发布。
  2. 阴影预算:最多使用 2 个投射阴影的 DirectionalLight。移动端补光使用
    fake_gi_bounce.gd
    。
  3. VFX 生命周期:使用
    finished
    signal,而非 Timer。通过
    restart()
    重新运行,避免异步 GPU 卡顿。
  4. 优化:使用
    ORM Texture
    打包(AO/Rough/Metal),节省 GPU 缓存和 texture slot。
  5. 批处理:使用
    Instance Uniforms
    为数千个实例创建材质变化,而不增加 draw call 惩罚。
[!CAUTION] 工作流 10 禁止事项
  • 绝不缩放
    CollisionShape
    节点;应严格缩放 Shape Resource,以避免物理抖动。
  • 对 cutout mesh(树叶、围栏)绝不使用
    TRANSPARENCY_ALPHA
    ;使用
    ALPHA_SCISSOR
    防止排序伪影。
  • 游戏过程中绝不动画 CSG 节点,否则会强制执行昂贵的 CPU 几何体重算。
  • 对于 2D 风格游戏,绝不使用实时 Global Illumination(SDFGI/VoxelGI)。应使用
    DirectionalLight2D
    和
    CanvasModulate
    。
  • 绝不忽略
    Camera3D
    的 near/far plane;设置不当会导致大型世界中的 Z-fighting。

Workflow 11: Programmatic Scene Building (Builder)

工作流 11:程序化场景构建(Builder)

MANDATORY: Builder Use ONLY for batch operations or complex procedural scaffolds. Prefer the standalone
godot-builder
skill when doing heavy CLI automation.
  1. Step 1: Draft the node hierarchy on paper/markdown before touching disk.
  2. Step 2: Use
    create_scene.py
    to define the root node and
    .tscn
    path.
  3. Step 3: Use
    add_node.py
    for children. Set
    owner
    on every node so serialization keeps them.
  4. Step 4: ALWAYS call
    run_project.py
    or
    launch_editor.py
    to verify the scene loads cleanly.
  5. Expert Rule: Use Builder to build the structure (nodes, names, inheritance), then use GDScript to build the behavior.
[!CAUTION] Workflow 11 NEVER List
  • NEVER jump straight to
    add_node.py
    without designing the hierarchy first — spaghetti scenes follow.
  • NEVER use absolute filesystem paths in scripts or scene props; use
    res://
    only.
  • NEVER add a
    CollisionShape2D
    /
    CollisionShape3D
    without assigning a Shape resource — the node alone does nothing.
  • NEVER skip verification via
    run_project.py
    /
    launch_editor.py
    after batch scene writes.
必须读取:Builder 仅用于批处理操作或复杂的程序化脚手架。执行繁重的 CLI 自动化时,优先使用独立的
godot-builder
skill。
  1. 步骤 1:接触磁盘之前,先在纸面或 markdown 中设计节点层级。
  2. 步骤 2:使用
    create_scene.py
    定义根节点和
    .tscn
    路径。
  3. 步骤 3:使用
    add_node.py
    添加子节点。为每个节点设置
    owner
    ,确保序列化时保留它们。
  4. 步骤 4:始终调用
    run_project.py
    或
    launch_editor.py
    ,验证场景能够干净加载。
  5. 专家规则:使用 Builder 构建结构(节点、名称、继承关系),再使用 GDScript 构建行为。
[!CAUTION] 工作流 11 禁止事项
  • 绝不在设计层级之前直接调用
    add_node.py
    ,否则会产生意大利面式场景。
  • 脚本或场景属性中绝不使用绝对文件系统路径;只能使用
    res://
    。
  • 添加
    CollisionShape2D
    /
    CollisionShape3D
    时,绝不不分配 Shape resource;仅添加节点不会产生任何效果。
  • 批量写入场景后,绝不跳过通过
    run_project.py
    /
    launch_editor.py
    进行的验证。

Security: Boundary Markers & Validation

安全:边界标记与验证

When agents ingest untrusted scene/data text before writing files:
  1. Boundary Markers: Wrap analysis in
    <<<CONTEXT_START>>>
    and
    <<<CONTEXT_END>>>
    .
  2. Sanitization: Node names must be alphanumeric/underscored. Paths must start with
    res://
    .
  3. Verification: Confirm scene existence before modification.

当 Agent 在写入文件前摄取不可信的场景或数据文本时:
  1. 边界标记:使用
    <<<CONTEXT_START>>>
    和
    <<<CONTEXT_END>>>
    包裹分析内容。
  2. 净化:节点名称只能包含字母、数字和下划线。路径必须以
    res://
    开头。
  3. 验证:修改前确认场景存在。

🚫 Part 4: The Expert NEVER List

🚫 第 4 部分:专家禁止事项清单

Each rule includes the non-obvious reason — the thing only shipping experience teaches.
  1. NEVER use
    get_tree().root.get_node("...")
    — Absolute paths break when ANY ancestor is renamed or reparented. Use
    %UniqueNames
    ,
    @export NodePath
    , or signal-based discovery.
  2. NEVER use
    load()
    inside a loop or
    _process
    — Synchronous disk read blocks the ENTIRE main thread. Use
    preload()
    at script top for small assets,
    ResourceLoader.load_threaded_request()
    for large ones.
  3. NEVER
    queue_free()
    while external references exist
    — Parent nodes or arrays holding refs will get "Deleted Object" errors. Clean up refs in
    _exit_tree()
    and set them to
    null
    before freeing.
  4. NEVER put gameplay logic in
    _draw()
    —
    _draw()
    is called on the rendering thread. Mutating game state causes race conditions with
    _physics_process
    .
  5. NEVER use
    Area2D
    for 1000+ overlapping objects
    — Each overlap check has O(n²) broadphase cost. Use
    ShapeCast2D
    ,
    PhysicsDirectSpaceState2D.intersect_shape()
    , or Server APIs for bullet-hell patterns.
  6. NEVER mutate external state from a component — If
    HealthComponent
    calls
    $HUD.update_bar()
    , deleting the HUD crashes the game. Components emit signals; listeners decide how to respond.
  7. NEVER use
    await
    in
    _physics_process
    —
    await
    yields execution, meaning the physics step skips frames. Move async operations to a separate method triggered by a signal.
  8. NEVER use
    String
    keys in hot-path dictionary lookups
    — String hashing is O(n). Use
    StringName
    (
    &"key"
    ) for O(1) pointer comparisons, or integer enums.
  9. NEVER store
    Callable
    references to freed objects
    — Crashes silently or throws errors. Disconnect signals in
    _exit_tree()
    or use
    CONNECT_ONE_SHOT
    .
  10. NEVER use
    _process
    for 1000+ entities
    — Each
    _process
    call has per-node SceneTree overhead. Use a single
    Manager._process
    that iterates an array of data structs (Data-Oriented pattern), or use Server APIs directly.
  11. NEVER use
    Tween
    on a node that may be freed
    — If a node is
    queue_free()
    'd while a Tween runs, it errors. Kill tweens in
    _exit_tree()
    or bind to SceneTree:
    get_tree().create_tween()
    .
  12. NEVER request data FROM
    RenderingServer
    or
    PhysicsServer
    in
    _process
    — These servers run asynchronously. Calling getter functions forces a synchronous stall that kills performance. The APIs are intentionally designed to be write-only in hot paths.
  13. NEVER use
    call_deferred()
    as a band-aid for initialization order bugs
    — It masks architectural problems (dependency on tree order). Fix the actual dependency with explicit initialization signals or
    @onready
    .
  14. NEVER create circular signal connections — Node A connects to B, B connects to A. This creates infinite loops on the first emit. Use a mediator pattern (Signal Bus) to break cycles.
  15. NEVER let inheritance exceed 3 levels — Beyond 3, debugging
    super()
    chains is a nightmare. Use composition (
    Node
    children) to add behaviors instead.
  16. NEVER use
    _process
    for hit detection or movement
    in physics-heavy genres (FPS/ARPG); strictly use
    _physics_process
    to ensure frame-independent collision detection.
  17. NEVER trust the client for authority on persistent game state (Health, XP, Inventory). Handled exclusively via Server-Auth or Secure Checksums.
  18. NEVER use standard strings for high-frequency runtime checks; strictly use
    StringName
    (&"active") to avoid O(n) hashing.
  19. NEVER manually handle RVO avoidance every frame in unit-heavy games (RTS/MOBA); offload to
    NavigationAgent
    internal threading.
  20. NEVER block the main thread for procedural generation or heavy I/O; strictly offload to
    WorkerThreadPool
    .
  21. NEVER ignore
    Local-to-Scene
    on Resources
    used in unique instances (e.g. enemy stats); failure causes shared-memory bugs across all instances.
  22. NEVER use
    float
    for currency
    ; strictly use Integer Cents to avoid precision drift in complex economies.
  23. NEVER set
    target_position
    before
    physics_frame
    ; navigation maps are not ready during
    _ready()
    .
  24. NEVER use
    TRANSPARENCY_HASH
    or
    ALPHA
    for large cutout surfaces (foliage); use
    ALPHA_SCISSOR
    for performance and sorting.
  25. NEVER scale
    CollisionShape
    nodes
    (Node2D/3D scale) — Use shape handles or resize the resource to avoid unpredictable physics normals and jitter.
  26. NEVER apply gravity while
    is_on_floor()
    is true
    — Causes micro-jitter and prevents floor-snapping; strictly reset vertical velocity to 0 or a small constant.
  27. NEVER forget to disconnect dynamic signals (Capturing Lambdas) — Godot cannot auto-disconnect lambdas that capture local variables; they will cause crashes on freed objects.
  28. NEVER use mouse events for mobile touch — Strictly use
    InputEventScreenTouch
    and
    InputEventScreenDrag
    for reliable multi-touch support.
  29. NEVER use Forward+ renderer for mobile — Strictly use Mobile or Compatibility renderers to avoid GPU bottlenecks and battery drain.
  30. NEVER accumulate mouse rotation directly on Transforms — Strictly store separate Yaw/Pitch variables to prevent gimbal lock and precision loss.
  31. NEVER use standard Strings for high-frequency runtime checks — Strictly use
    StringName
    (&"active") to avoid O(n) hashing overhead.
  32. NEVER trust the client for game state (Health, Inventory) — Clients suggest actions; Server validates and broadcasts to prevent cheating.
  33. NEVER use
    Reliable
    RPCs for movement updates
    — Use
    UnreliableOrdered
    to prevent Head-of-Line blocking in high-latency scenarios.

每条规则都包含不显而易见的深层原因——这是实际交付经验才能传授的知识。
  1. 绝不使用
    get_tree().root.get_node("...")
    ——只要任意祖先被重命名或重新设置父节点,绝对路径就会失效。使用
    %UniqueNames
    、
    @export NodePath
    或基于 signal 的发现机制。
  2. 绝不在循环或
    _process
    中使用
    load()
    ——同步磁盘读取会阻塞整个主线程。小型 asset 应在脚本顶部使用
    preload()
    ,大型 asset 应使用
    ResourceLoader.load_threaded_request()
    。
  3. 当外部引用仍存在时,绝不调用
    queue_free()
    ——父节点或持有引用的数组会导致“Deleted Object”错误。在
    _exit_tree()
    中清理引用,并在释放前将其设为
    null
    。
  4. 绝不将游戏逻辑放在
    _draw()
    中
    ——
    _draw()
    会在渲染线程上调用。修改游戏状态会与
    _physics_process
    产生竞态条件。
  5. 绝不对 1,000+ 个重叠对象使用
    Area2D
    ——每次重叠检测都有 O(n²) broadphase 成本。对于 bullet-hell 模式,使用
    ShapeCast2D
    、
    PhysicsDirectSpaceState2D.intersect_shape()
    或 Server API。
  6. 绝不从组件修改外部状态——如果
    HealthComponent
    调用
    $HUD.update_bar()
    ,删除 HUD 就会使游戏崩溃。组件应发出 signal,由监听者决定如何响应。
  7. 绝不在
    _physics_process
    中使用
    await
    ——
    await
    会产生执行权移交,导致物理步跳过帧。将异步操作移到由 signal 触发的独立方法中。
  8. 绝不在热点 Dictionary 查找中使用
    String
    键
    ——String 哈希为 O(n)。使用
    StringName
    (
    &"key"
    )进行 O(1) 指针比较,或使用整数枚举。
  9. 绝不保存指向已释放对象的
    Callable
    引用
    ——这会静默崩溃或抛出错误。在
    _exit_tree()
    中断开 signal,或使用
    CONNECT_ONE_SHOT
    。
  10. 绝不对 1,000+ 实体使用
    _process
    ——每次
    _process
    调用都有逐节点 SceneTree 开销。使用单个
    Manager._process
    遍历数据结构数组(Data-Oriented 模式),或直接使用 Server API。
  11. 绝不在可能被释放的节点上使用
    Tween
    ——如果节点在 Tween 运行期间被
    queue_free()
    ,就会出错。在
    _exit_tree()
    中终止 Tween,或绑定到 SceneTree:
    get_tree().create_tween()
    。
  12. 绝不在
    _process
    中向
    RenderingServer
    或
    PhysicsServer
    请求数据
    ——这些服务器异步运行。调用 getter 会强制同步等待,严重损害性能。这些 API 在热点路径中被有意设计为只写。
  13. 绝不将
    call_deferred()
    当作初始化顺序问题的临时补救措施
    ——它会掩盖架构问题(对树顺序的依赖)。应使用显式初始化 signal 或
    @onready
    修复实际依赖关系。
  14. 绝不创建循环 signal 连接——Node A 连接 Node B,Node B 又连接 Node A。第一次 emit 就会产生无限循环。使用中介者模式(Signal Bus)打破循环。
  15. 绝不让继承层级超过 3 层——超过 3 层后,调试
    super()
    调用链会非常困难。应使用组合(
    Node
    子节点)添加行为。
  16. 在物理密集类型(FPS/ARPG)中,绝不使用
    _process
    进行命中检测或移动
    ;严格使用
    _physics_process
    ,确保碰撞检测与帧率无关。
  17. 绝不在持久游戏状态(Health、XP、Inventory)上信任客户端权威。只能通过 Server-Auth 或 Secure Checksums 处理。
  18. 绝不在高频运行时检查中使用普通 String;严格使用
    StringName
    (
    &"active"
    ),避免 O(n) 哈希。
  19. 绝不在单位密集型游戏(RTS/MOBA)中每帧手动处理 RVO 避让;应交给
    NavigationAgent
    的内部线程处理。
  20. 绝不阻塞主线程执行程序化生成或繁重 I/O;严格将其卸载到
    WorkerThreadPool
    。
  21. 绝不忽略唯一实例所用 Resource 的
    Local-to-Scene
    (例如 enemy stats);否则会在所有实例间产生共享内存 Bug。
  22. 绝不使用
    float
    表示货币
    ;严格使用整数美分,避免复杂经济系统中的精度漂移。
  23. 绝不在
    physics_frame
    之前设置
    target_position
    ;
    _ready()
    期间 navigation map 尚未就绪。
  24. 绝不对大型 cutout 表面(树叶)使用
    TRANSPARENCY_HASH
    或
    ALPHA
    ;使用
    ALPHA_SCISSOR
    提升性能并改善排序。
  25. 绝不缩放
    CollisionShape
    节点
    (Node2D/3D scale)——应调整 handle 或调整 resource 尺寸,以避免不可预测的 physics normal 和抖动。
  26. 绝不在
    is_on_floor()
    为 true 时施加重力
    ——这会造成微抖动并阻止地面吸附;应将垂直速度严格重置为 0 或一个很小的常量。
  27. 绝不忘断开捕获 Lambda 的动态 signal——Godot 无法自动断开捕获局部变量的 Lambda;它们会在对象释放后导致崩溃。
  28. 绝不为移动端触控使用鼠标事件——严格使用
    InputEventScreenTouch
    和
    InputEventScreenDrag
    ,以可靠支持多点触控。
  29. 绝不在移动端使用 Forward+ renderer——严格使用 Mobile 或 Compatibility renderer,以避免 GPU 瓶颈和电量消耗。
  30. 绝不直接在 Transform 上累积鼠标旋转——应分别存储 Yaw/Pitch,以避免万向节锁和精度损失。
  31. 绝不在高频运行时检查中使用普通 String——严格使用
    StringName
    (
    &"active"
    ),避免 O(n) 哈希开销。
  32. 绝不在游戏状态(Health、Inventory)上信任客户端——Client 仅建议动作,由 Server 验证和广播,以防止作弊。
  33. 绝不使用
    Reliable
    RPC 传输移动更新
    ——使用
    UnreliableOrdered
    ,避免高延迟场景中的 Head-of-Line Blocking。

📊 Part 5: Performance Budgets (Concrete Numbers)

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

MetricMobile TargetDesktop TargetExpert Note
Draw Calls< 100 (2D), < 200 (3D)< 500
MultiMeshInstance
for foliage/debris
Triangle Count< 100K visible< 1M visibleLOD system mandatory above 500K
Texture VRAM< 512MB< 2GBVRAM Compression: ETC2 (mobile), BPTC (desktop)
Script Time< 4ms per frame< 8ms per frameMove hot loops to Server APIs
Physics Bodies< 200 active< 1000 activeUse
PhysicsServer
direct API for mass sim
Particles< 2000 total< 10000 totalGPU particles, set
visibility_aabb
manually
Audio Buses< 8 simultaneous< 32 simultaneousUse Audio Systems bus routing
Save File Size< 1MB< 50MBSeed + Delta pattern for procedural worlds
Scene Load Time< 500ms< 2s
ResourceLoader.load_threaded_request()

指标移动端目标桌面端目标专家说明
Draw Calls< 100(2D),< 200(3D)< 500树叶/碎片使用
MultiMeshInstance
三角形数量< 100K 可见< 1M 可见超过 500K 时必须使用 LOD 系统
Texture VRAM< 512MB< 2GBVRAM Compression:移动端 ETC2,桌面端 BPTC
脚本时间每帧 < 4ms每帧 < 8ms将热点循环迁移至 Server API
物理刚体< 200 个活跃< 1000 个活跃大规模模拟直接使用
PhysicsServer
API
Particles总计 < 2000总计 < 10000使用 GPU particles,并手动设置
visibility_aabb
Audio Buses同时 < 8同时 < 32使用 Audio Systems 的 bus routing
存档大小< 1MB< 50MB程序化世界使用 Seed + Delta 模式
场景加载时间< 500ms< 2s使用
ResourceLoader.load_threaded_request()

⚙️ Part 6: Server APIs — The Expert Performance Escape Hatch

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

This is knowledge most Godot developers never learn. When the scene tree becomes a bottleneck, bypass it entirely using Godot's low-level Server APIs.
这是多数 Godot 开发者永远不会接触到的知识。当场景树成为瓶颈时,可使用 Godot 的底层 Server API 完全绕过它。

When to Drop to Server APIs

何时切换到 Server API

  • 10K+ rendered instances (sprites, meshes): Use
    RenderingServer
    with RIDs instead of
    Sprite2D
    /
    MeshInstance3D
    nodes.
  • Bullet-hell / particle systems with script interaction: Use
    PhysicsServer2D
    body creation instead of
    Area2D
    nodes.
  • Mass physics simulation: Use
    PhysicsServer3D
    directly for ragdoll fields, debris, or fluid-like simulations.
  • 10K+ 渲染实例(sprite、mesh):使用带 RID 的
    RenderingServer
    ,而不是
    Sprite2D
    /
    MeshInstance3D
    节点。
  • 需要脚本交互的 Bullet-hell/粒子系统:使用
    PhysicsServer2D
    创建刚体,而不是
    Area2D
    节点。
  • 大规模物理模拟:直接使用
    PhysicsServer3D
    实现 ragdoll 场、碎片或类流体模拟。

📊 Performance Comparison: SceneTree vs. Server APIs

📊 性能对比:SceneTree 与 Server API

Bypassing the SceneTree eliminates the heavy CPU overhead of node lifecycle management, signal propagation, and virtual function overhead (like
_process
).
MetricSceneTree (Nodes)Server APIs (RIDs)Expert Rationale
Object Limit~1,000 - 5,00050,000+SceneTree has O(n) traversal costs; Servers use O(1) direct RID handles.
Memory Overhead~2KB - 10KB per Node< 200 bytes per RIDNodes carry tree state, signals, and inspector metadata. RIDs are opaque 24-byte handles.
CPU TimeHigh (Virtual calls)Minimal (Direct API)Nodes must call
_process
for every instance. Servers batch operations in C++.
ThreadingMain Thread OnlyInherently Thread-SafeMost Server APIs are thread-safe (must be enabled in Project Settings).
Garbage CollectionAutomatic (RefCounted)Manual (Alloc/Free)Servers require manual lifecycle management (RID creation/deletion).
Expert Note: Using RIDs allows managing raw data and interacting directly with engine core logic. This is the primary "escape hatch" for bullet-hells, massive foliage, or complex procedural simulations where SceneTree housekeeping becomes the bottleneck.
绕过 SceneTree 可以消除节点生命周期管理、signal 传播和
_process
等虚拟函数调用带来的沉重 CPU 开销。
指标SceneTree(Nodes)Server API(RIDs)专家原理
对象上限约 1,000 - 5,00050,000+SceneTree 有 O(n) 遍历成本;Server 使用 O(1) 的直接 RID handle。
内存开销每个 Node 约 2KB - 10KB每个 RID < 200 bytesNode 携带树状态、signal 和 Inspector 元数据;RID 是不透明的 24-byte handle。
CPU 时间高(虚函数调用)极低(直接 API)每个实例都必须由 Node 调用
_process
;Server 在 C++ 中批量执行操作。
线程处理仅限主线程天然线程安全多数 Server API 是线程安全的,但必须在 Project Settings 中启用。
垃圾回收自动(RefCounted)手动(Alloc/Free)Server 要求手动管理 RID 生命周期(创建/删除)。
专家说明:使用 RID 可以管理原始数据并直接与引擎核心逻辑交互。对于 bullet-hell、大规模树叶或复杂程序化模拟,当 SceneTree 管理工作成为瓶颈时,这是主要的“逃生通道”。

The RID Pattern (Expert)

RID 模式(专家级)

Server APIs communicate through RID (Resource ID) — opaque handles to server-side objects. Critical rules:
gdscript
undefined
Server API 通过 RID(Resource ID)通信——它是服务器端对象的不透明 handle。关键规则:
gdscript
undefined

Create server-side canvas item (NO node overhead)

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())
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.

CRITICAL: Keep resource references alive. RIDs don't count as references.

If the Texture resource is GC'd, the RID becomes invalid silently.

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)
undefined
var texture: Texture2D = preload("res://sprite.png") RenderingServer.canvas_item_add_texture_rect(ci_rid, Rect2(-texture.get_size() / 2, texture.get_size()), texture)
undefined

Threading with Servers

使用 Server 进行线程处理

  • The scene tree is NOT thread-safe. But Server APIs (RenderingServer, PhysicsServer) ARE thread-safe when enabled in Project Settings.
  • You CAN build scene chunks (instantiate + add_child) on a worker thread, but MUST use
    add_child.call_deferred()
    to attach them to the live tree.
  • GDScript Dictionaries/Arrays: reads and writes across threads are safe, but resizing (append, erase, resize) requires a
    Mutex
    .
  • NEVER load the same
    Resource
    from multiple threads simultaneously — use one loading thread.

  • 场景树不是线程安全的。但启用 Project Settings 后,Server API(RenderingServer、PhysicsServer)是线程安全的。
  • 可以在 worker thread 上构建场景 chunk(实例化并执行
    add_child
    ),但必须使用
    add_child.call_deferred()
    将其附加到活动场景树。
  • GDScript Dictionary/Array:跨线程读取和写入是安全的,但调整大小(append、erase、resize)需要
    Mutex
    。
  • 绝不从多个线程同时加载同一个
    Resource
    ——应只使用一个加载线程。

🧩 Part 7: Expert Code Patterns

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

Expert implementations of common architectural and gameplay systems.
  • Component Registry: Centralized dictionary-based component retrieval.
  • Safe Signal Handler: Preventing crashes on freed object references.
  • Async Resource Loader: Threaded asset ingestion.
  • State Machine Transition Guard: Validating state changes.
  • Thread-Safe Chunk Loader: Low-level server-api construction.
  • Vision Cone Detection: Expert NPC vision with dot products and raycasts.
  • Sound Propagation System: Acoustic occlusion logic.
  • Stealth Hiding Logic: Global visibility and concealment management.

常见架构和游戏系统的专家实现。
  • Component Registry:基于 Dictionary 的集中式组件检索。
  • Safe Signal Handler:防止访问已释放对象引用时崩溃。
  • Async Resource Loader:线程化 asset 加载。
  • State Machine Transition Guard:验证状态变化。
  • Thread-Safe Chunk Loader:底层 Server API 构建。
  • Vision Cone Detection:使用点积和 raycast 的专家级 NPC 视野。
  • Sound Propagation System:声学遮挡逻辑。
  • Stealth Hiding Logic:全局可见性与隐蔽管理。

🔥 Part 8: Godot 4.x Gotchas (Veteran-Only)

🔥 第 8 部分:Godot 4.x 陷阱(资深用户专属)

  1. @export
    Resources are shared by default
    : Multiple scene instances ALL share the same
    Resource
    . Use
    resource.duplicate()
    in
    _ready()
    or enable "Local to Scene" checkbox. This is the #1 most reported Godot 4 bug by newcomers.
  2. Signal syntax silently fails:
    connect("signal_name", target, "method")
    (Godot 3 syntax) compiles but does nothing in Godot 4. Must use
    signal_name.connect(callable)
    .
  3. Tween
    is no longer a Node
    : Created via
    create_tween()
    , bound to the creating node's lifetime. If that node is freed, the Tween dies. Use
    get_tree().create_tween()
    for persistent tweens.
  4. PhysicsBody
    layers vs masks
    :
    collision_layer
    = "what I am".
    collision_mask
    = "what I scan for". Setting both to the same value causes self-collision or missed detections.
  5. StringName
    vs
    String
    in hot paths
    :
    StringName
    (
    &"key"
    ) uses pointer comparison (O(1)).
    String
    uses character comparison (O(n)). Always use
    StringName
    for dictionary keys in
    _process
    .
  6. @onready
    timing
    : Runs AFTER
    _init()
    but DURING
    _ready()
    . If you need constructor-time setup, use
    _init()
    . If you need tree access, use
    @onready
    or
    _ready()
    . Mixing them causes nulls.
  7. Server query stalls: Calling
    RenderingServer
    or
    PhysicsServer
    getter functions in
    _process
    forces a synchronous pipeline flush. These servers run async — requesting data from them stalls the entire pipeline until the server catches up.
  8. move_and_slide()
    API change
    : Returns
    bool
    (whether collision occurred). Velocity is now a property, not a parameter.
    velocity = dir * speed
    before calling
    move_and_slide()
    .

  1. @export
    Resource 默认共享
    :多个场景实例会共享同一个
    Resource
    。在
    _ready()
    中使用
    resource.duplicate()
    ,或启用“Local to Scene”复选框。这是 Godot 4 新手反馈最多的 Bug #1。
  2. Signal 语法会静默失效:
    connect("signal_name", target, "method")
    (Godot 3 语法)虽然能编译,但在 Godot 4 中不会执行任何操作。必须使用
    signal_name.connect(callable)
    。
  3. Tween
    不再是 Node
    :通过
    create_tween()
    创建,并绑定到创建它的节点生命周期。如果该节点被释放,Tween 也会消失。对于持久 Tween,使用
    get_tree().create_tween()
    。
  4. PhysicsBody 的 layer 与 mask:
    collision_layer
    表示“我是什么”,
    collision_mask
    表示“我检测什么”。将两者设为相同值会导致自碰撞或漏检。
  5. 热点路径中的
    StringName
    与
    String
    :
    StringName
    (
    &"key"
    )使用指针比较(O(1));
    String
    使用字符比较(O(n))。在
    _process
    中,Dictionary 键始终使用
    StringName
    。
  6. @onready
    时序
    :它在
    _init()
    之后、
    _ready()
    期间运行。如果需要构造时初始化,使用
    _init()
    ;如果需要访问场景树,使用
    @onready
    或
    _ready()
    。混用会导致空值。
  7. Server 查询卡顿:在
    _process
    中调用
    RenderingServer
    或
    PhysicsServer
    getter 会强制同步刷新 pipeline。这些服务器异步运行;在
    _process
    中请求数据会使整个 pipeline 停滞,直到服务器完成追赶。
  8. move_and_slide()
    API 变化
    :返回
    bool
    (是否发生碰撞)。Velocity 现在是属性,而不是参数。调用
    move_and_slide()
    前先设置
    velocity = dir * speed
    。

📂 Part 9: Module Directory (99 Blueprints)

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

[!IMPORTANT] Load ONLY the modules needed for your current workflow. Use the Decision Matrix in Part 2 to determine which chain to follow.
[!IMPORTANT] 仅加载当前工作流所需的模块。使用第 2 部分的决策矩阵确定应遵循的链路。

Architecture & Foundation

架构与基础

Foundations | Composition | App Composition | Signals | Autoloads | States | Resources | Templates | Analyst | Auditor | Builder
Version upgrades (external hub): godot-version-migration — full-history router (legacy eras, 3→4 bridge, 4.0→4.7 hops); not mirrored here.
Foundations | Composition | App Composition | Signals | Autoloads | States | Resources | Templates | Analyst | Auditor | Builder
版本升级(外部中心): godot-version-migration——完整历史路由(旧版本、3→4 桥接、4.0→4.7 逐版本升级);此处未镜像。

GDScript & Testing

GDScript 与测试

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

2D Systems

2D 系统

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

3D Systems

3D 系统

3D Lighting | 3D Materials | 3D World Building | Physics 3D | Navigation/Pathfinding | Procedural Generation | Raycasting
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
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 与 UX

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

Connectivity & Platforms

连接与平台

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

Adaptation Guides

适配指南

  • Adapting Desktop -> Mobile
  • Adapting Mobile -> Desktop
  • Adapting Single -> Multiplayer
  • Adapting 2D -> 3D
  • Adapting 3D -> 2D
  • Adapting Desktop -> Mobile
  • Adapting Mobile -> Desktop
  • Adapting Single -> Multiplayer
  • Adapting 2D -> 3D
  • Adapting 3D -> 2D

Genre Blueprints (Exhaustive)

类型蓝图(完整)

Action RPG | Shooter | Shooter FPS | RTS | MOBA | Rogue-like | Survival | Open World | Metroidvania | Platformer | Fighting | Stealth | Sandbox | Horror | Puzzle | Racing | Rhythm | Sports | Battle Royale | Card Game | Visual Novel | Romance | Simulation | Tower Defense | Idle Clicker | Party | Educational

Action RPG | Shooter | Shooter FPS | RTS | MOBA | Rogue-like | Survival | Open World | Metroidvania | Platformer | Fighting | Stealth | Sandbox | Horror | Puzzle | Racing | Rhythm | Sports | Battle Royale | Card Game | Visual Novel | Romance | Simulation | Tower Defense | Idle Clicker | Party | Educational

🐛 Part 10: Expert Diagnostic Patterns

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

The "Invisible Node" Bug

“隐形节点”Bug

Symptom: Node exists in tree but isn't rendering. Expert diagnosis chain:
visible
property →
z_index
→ parent
CanvasLayer
wrong layer →
modulate.a == 0
→ behind camera's
near
clip (3D) →
SubViewport.render_target_update_mode
not set →
CanvasItem
not in any
CanvasLayer
(renders behind everything).
症状:节点存在于场景树中,但没有显示。 专家诊断链:
visible
属性 →
z_index
→ 父级
CanvasLayer
层级错误 →
modulate.a == 0
→ 位于相机
near
裁剪面之后(3D)→ 未设置
SubViewport.render_target_update_mode
→
CanvasItem
不属于任何
CanvasLayer
(渲染在其他内容之后)。

The "Input Eaten" Bug

“输入被吞掉”Bug

Symptom: Clicks or key presses ignored intermittently. Expert diagnosis: Another
Control
node with
mouse_filter = STOP
overlapping the target. Or, modal
PopupMenu
consuming unhandled input. Or,
_unhandled_input()
in another script calling
get_viewport().set_input_as_handled()
.
症状:点击或按键偶尔被忽略。 专家诊断:另一个
Control
节点的
mouse_filter = STOP
与目标重叠;或模态
PopupMenu
消费了未处理输入;或另一个脚本中的
_unhandled_input()
调用了
get_viewport().set_input_as_handled()
。

The "Physics Jitter" Bug

“物理抖动”Bug

Symptom: Character vibrates at surface contacts. Expert diagnosis:
Safe Margin
too large. Or,
_process
used for movement instead of
_physics_process
(interpolation mismatch). Or, collision shapes overlap at spawn (push each other apart permanently).
症状:角色在表面接触时振动。 专家诊断:
Safe Margin
过大;或移动时使用
_process
而非
_physics_process
,导致插值不匹配;或碰撞形状在生成时相互重叠,从而持续互相排斥。

The "Memory Leak"

“内存泄漏”

Symptom: RAM grows steadily during play. Expert diagnosis:
queue_free()
called but reference held in Array/Dictionary. Or, signals connected with
CONNECT_REFERENCE_COUNTED
without cleanup. Use Profiler "Objects" tab to find orphaned instances. Search for
Node
instances without a parent.
症状:游戏过程中 RAM 持续增长。 专家诊断:调用了
queue_free()
,但 Array/Dictionary 中仍持有引用;或使用
CONNECT_REFERENCE_COUNTED
连接 signal 后未清理。使用 Profiler 的“Objects”标签查找孤立实例,并搜索没有父节点的
Node
实例。

The "Frame Spike"

“帧峰值”

Symptom: Smooth FPS but periodic drops. Expert diagnosis: GDScript GC pass. Or, synchronous
load()
for a large resource. Or,
NavigationServer
rebaking. Or, Server API query stall (requesting data from
RenderingServer
in
_process
). Profile with built-in Profiler → look for function-level spikes.

症状:FPS 平稳,但周期性下降。 专家诊断:GDScript GC 扫描;同步
load()
大型 resource;
NavigationServer
重新烘焙;或 Server API 查询停顿(在
_process
中向
RenderingServer
请求数据)。使用内置 Profiler 定位函数级峰值。

🚀 Part 11: Quick Start — Unity (C#) to Godot (GDScript)

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

Mental model shifts for senior engineers transitioning from the Unity ecosystem.
面向从 Unity 生态迁移的资深工程师,介绍需要转变的心智模型。

1. Nodes vs. GameObjects & Components

1. Node 与 GameObject/Components

In Unity, a
GameObject
is a container for
Components
. In Godot, everything is a Node.
  • Unity:
    GameObject
    +
    Transform
    +
    MeshFilter
    +
    Script
    .
  • Godot: A
    MeshInstance3D
    node (which is a Transform and a Mesh) with a script attached.
  • Expert Shift: Use Node composition. If you need a "Health Component", add a
    Node
    or
    Area3D
    as a child called "Health". Use
    RefCounted
    for logic-only components to save memory.
在 Unity 中,
GameObject
是
Components
的容器。而在 Godot 中,一切都是 Node。
  • Unity:
    GameObject
    +
    Transform
    +
    MeshFilter
    +
    Script
    。
  • Godot:
    MeshInstance3D
    节点(它本身就是 Transform 和 Mesh)并附加脚本。
  • 专家思维转变:使用 Node 组合。如果需要“Health Component”,可添加名为“Health”的
    Node
    或
    Area3D
    子节点。对于纯逻辑组件,使用
    RefCounted
    以节省内存。

2. Scenes are Nested Prefabs

2. Scene 就是嵌套 Prefab

Godot doesn't have "Prefabs" because every scene is a prefab.
  • You can instantiate a scene inside another scene, infinitely.
  • Expert Shift: Every reusable system (Player, Enemy, UI Button) should be its own
    .tscn
    file. This promotes "Post-Order Traversal" (children are ready before parents).
Godot 没有单独的“Prefab”概念,因为每个场景都是 Prefab。
  • 可以在另一个场景中无限嵌套实例化场景。
  • 专家思维转变:每个可复用系统(Player、Enemy、UI Button)都应是独立的
    .tscn
    文件。这有助于采用“Post-Order Traversal”(子节点先于父节点就绪)。

3. Signals vs. Events/Actions

3. Signal 与 Event/Action

Godot's
Signal
system is a native implementation of the Observer pattern.
  • Unity:
    event Action OnDeath;
    .
  • Godot:
    signal died
    .
  • Expert Shift: Signals are first-class citizens. They are visible in the Inspector and can be connected dynamically or via the editor. Use the "Signal Bus" pattern (Autoload) for global events to mimic Unity's Singleton managers.
Godot 的
Signal
系统是 Observer 模式的原生实现。
  • Unity:
    event Action OnDeath;
    。
  • Godot:
    signal died
    。
  • 专家思维转变:Signal 是一等公民,可在 Inspector 中查看,并可在编辑器或运行时动态连接。使用“Signal Bus”模式(Autoload)处理全局事件,以模拟 Unity 的 Singleton manager。

4. Scripts as Class Extensions

4. Script 作为类扩展

When you attach a script to a node, that script is the node.
  • Unity:
    GetComponent<MyScript>()
    .
  • Godot: The script extends the node's class (e.g.,
    extends CharacterBody3D
    ).
  • Expert Shift: Use Typed GDScript (
    var x: int = 5
    ) to gain compilation speedups and editor completion. Typed GDScript uses optimized opcodes when types are known at compile time.
将脚本附加到节点后,该脚本就是该节点。
  • Unity:
    GetComponent<MyScript>()
    。
  • Godot:脚本
    extends
    节点类(例如
    extends CharacterBody3D
    )。
  • 专家思维转变:使用 Typed GDScript(
    var x: int = 5
    )获得编译速度提升和 Editor 自动补全。类型已知时,Typed GDScript 可使用优化后的 opcode。

5. Memory Management: No Garbage Collection stalls

5. 内存管理:没有 GC 卡顿

Unlike Unity's C# which can have "GC spikes", GDScript uses Reference Counting.
  • Expert Shift: Objects are freed the moment they are no longer referenced. This provides deterministic performance and avoids the intermittent "stutters" common in large Unity projects.
与可能产生“GC spike”的 Unity C# 不同,GDScript 使用引用计数。
  • 专家思维转变:对象在不再被引用后会立即释放。这可提供确定性的性能表现,并避免大型 Unity 项目中常见的间歇性“stutter”。

6. StringNames & Performance

6. StringNames 与性能

Unity uses
int
or
Enum
for performance. Godot uses
StringName
.
  • Expert Shift: Use
    &"name"
    for constant-time (O(1)) pointer comparisons in dictionaries and signal lookups.

Unity 为性能使用
int
或
Enum
,而 Godot 使用
StringName
。
  • 专家思维转变:使用
    &"name"
    在 Dictionary 和 signal 查找中执行恒定时间(O(1))的指针比较。

Reference

参考