godot-master
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGodot 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 owns health, NOT the
StatsComponent)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 signal)
health_changed
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() - 谁需要知道它发生了变化?(任何监听 signal 的对象)
health_changed
如果无法为每个状态变量回答这三个问题,你的架构就存在耦合问题。这并非普通的 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 node is calling , the architecture is broken.
Labelplayer.health -= 1将每个功能组织为四层。Signal 只能向上传递,绝不能向下传递:
┌──────────────────────────────┐
│ PRESENTATION(表现层:UI / VFX) │ ← 监听 signal,绝不拥有数据
├──────────────────────────────┤
│ LOGIC(逻辑层:状态机) │ ← 编排转换并查询数据
├──────────────────────────────┤
│ DATA(数据层:Resources / .tres) │ ← 单一事实来源,可序列化
├──────────────────────────────┤
│ INFRASTRUCTURE(基础设施层) │ ← Signal Bus、SaveManager、AudioBus
└──────────────────────────────┘关键规则:PRESENTATION 绝不能直接修改 DATA。INFRASTRUCTURE 只能通过 signal 通信。如果 节点正在执行 ,则架构已经失效。
Labelplayer.health -= 1The Signal Bus Tiered Architecture
分层 Signal Bus 架构
- Global Bus (Autoload): ONLY for lifecycle events (,
match_started,player_died). Debugging sprawl is the cost — limit events to < 15.settings_changed - Scoped Feature Bus: Each feature folder has its own bus (e.g., only for combat nodes). This is the compromise that scales.
CombatBus - Direct Signals: Parent-child communication WITHIN a single scene. Never across scene boundaries.
- Global Bus(Autoload):仅用于生命周期事件(、
match_started、player_died)。代价是调试代码蔓延——应将事件限制在 15 个以内。settings_changed - 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: and
PhysicsServer2DbypassRenderingServernode overhead. Use for 1,000+ bullets or particles to achieve O(1) processing.SceneTree - Animation → Physics: converts animation displacement into physics
AnimationTree.get_root_motion_position(), preventing "foot sliding" in complex movement.velocity - Data → Reactivity: Serialized objects (like
Resource) emit signals when modified, allowing UI to update automatically without tight coupling.Stats - Asset → Spawning: An O(1) Dictionary-based cache (preloaded during async phases) prevents I/O hitches when spawning items or enemies.
ResourceLoader - 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 for synchronization instead of JSON/Strings to keep packets under 100 bytes.
PackedByteArray - Genre Synthesis:
- : strictly use
Shooter(direct space state) overintersect_ray()nodes for 100x performance.RayCast3D - : Damage follows
RPGto sustain end-game progression.base * pow(scaling, level) - : Moves groups based on their Center of Mass with
RTSto preserve formation integrity.Relative Offset - : Uses
Metroidvaniafor seamless room swaps.ResourceLoader.load_threaded_request() - : Mandatory
Platformer(~0.15s) andJump Bufferingfor professional feel.Coyote Time - :
Simulationbatch processing; avoid per-entityTick Managerto sustain thousands of units._process - :
Romance(Attraction, Trust, Comfort) to map complex narrative branching.Multi-Axial Affection - :
Architecturestrictly followsSignal Architectureto eliminate circular scene coupling.Signal Up, Call Down
专家系统的关键不在于隔离,而在于 Payload Synthesis(载荷综合)。
- Physics → Performance:和
PhysicsServer2D可绕过RenderingServer的节点开销。对于 1,000+ 子弹或粒子,使用它们可实现 O(1) 处理。SceneTree - Animation → Physics:可将动画位移转换为物理
AnimationTree.get_root_motion_position(),避免复杂移动中的“脚滑”。velocity - Data → Reactivity:序列化后的 对象(例如
Resource)在修改时发出 signal,使 UI 可自动更新且不会形成紧密耦合。Stats - Asset → Spawning:基于 的 O(1) 缓存(在
Dictionary异步阶段预加载)可避免生成物品或敌人时发生 I/O 卡顿。ResourceLoader - Mobile → Visuals:在加载画面期间实例化隐藏特效,强制完成 GPU shader pipeline 编译,从而防止运行时帧卡顿。
- Networking → Bandwidth:同步时使用 进行位打包,而非 JSON/Strings,从而将数据包控制在 100 bytes 以内。
PackedByteArray - 类型综合:
- (射击游戏):严格使用
Shooter(直接空间状态),而非intersect_ray()节点,性能可提升 100 倍。RayCast3D - :伤害采用
RPG,以维持终局阶段的成长性。base * pow(scaling, level) - :根据群体的 Center of Mass 移动,并使用
RTS保持阵型完整性。Relative Offset - :使用
Metroidvania实现无缝房间切换。ResourceLoader.load_threaded_request() - :必须实现
Platformer(约 0.15 秒)和Jump Buffering,以获得专业级操作手感。Coyote Time - :使用
Simulation批处理;避免对每个实体调用Tick Manager,以维持数千单位同时运行。_process - :采用
Romance(Attraction、Trust、Comfort)映射复杂的叙事分支。Multi-Axial Affection - :
Architecture严格遵循“Signal 向上、调用向下”,从而消除循环场景耦合。Signal Architecture
🧭 Part 2: Architectural Decision Frameworks
🧭 第 2 部分:架构决策框架
The Master Decision Matrix
首席决策矩阵
| Scenario | Strategy | MANDATORY Skill Chain | Trade-off |
|---|---|---|---|
| Rapid Prototype | Event-Driven Mono | READ: Foundations → Autoloads. Do NOT load genre or platform refs. | Fast start, spaghetti risk |
| Complex RPG | Component-Driven | READ: Composition → States → RPG Stats. Do NOT load multiplayer or platform refs. | Heavy setup, infinite scaling |
| Massive Open World | Resource-Streaming | READ: Open World → Save/Load. Also load Performance. | Complex I/O, float precision jitter past 10K units |
| Server-Auth Multi | Deterministic | READ: Server Arch → Multiplayer. Do NOT load single-player genre refs. | High latency, anti-cheat secure |
| Mobile/Web Port | Adaptive-Responsive | READ: UI Containers → Adapt Desk→Mobile → Platform Mobile. | UI complexity, broad reach |
| Application / Tool | App-Composition | READ: App Composition → Theming. Do NOT load game-specific refs. | Different paradigm than games |
| Romance / Dating Sim | Affection Economy | READ: Romance → Dialogue → UI Rich Text. | High UI/Narrative density |
| Secrets / Easter Eggs | Intentional Obfuscation | READ: Secrets → Persistence. | Community engagement, debug risk |
| Collection Quest | Scavenger Logic | READ: Collections → Marker3D Placement. | Player retention, exploration drive |
| Seasonal Event | Runtime Injection | READ: Easter Theming → Material Swapping. | Fast branding, no asset pollution |
| Souls-like Mortality | Risk-Reward Revival | READ: Revival/Corpse Run → Physics 3D. | High tension, player frustration risk |
| Wave-based Action | Combat Pacing Loop | READ: Waves → Combat. | Escalating tension, encounter design |
| Balance / Difficulty / Economy Pacing | Monte Carlo Balance Lab | READ: Resources → Economy → Combat / RPG Stats / Waves (as needed) → Monte Carlo Balancer → Testing → Builder. | Statistical rigor; abstract sim must calibrate vs headless Godot |
| Survival Economy | Harvesting Loop | READ: Harvesting → Inventory. | Resource scarcity, loop persistence |
| Racing / Speedrun | Validation Loop | READ: Time Trials → Input Buffer → Genre Racing. | High precision, ghost record drive |
| Horror / Stealth | Tension Management | READ: Genre Horror → Genre Stealth → Audio. | Atmosphere, player vulnerability |
| Card / Board Game | Rule Enforcement | READ: Genre Card Game → Turn System. | Deterministic state, UI heavy |
| Simulation / RTS | Batch Processing | READ: Genre Simulation → Genre RTS → Performance. | High unit counts, O(1) logic |
| HDR / Cinematic Visuals | Display Pipeline | READ: 3D Lighting → Platform Desktop → Shaders. Enable viewport HDR in Project Settings. | Platform-specific tonemapping tuning |
| Rectangular Area Lights | AreaLight3D | READ: 3D Lighting → 3D Materials. Prefer AreaLight3D over emissive+GI hacks. | Forward+ renderer required for full quality |
| Mobile Touch Controls | Native Joystick | READ: Platform Mobile → Adapt Desk→Mobile. Use built-in virtual joystick (4.7+). | Less plugin dependency |
| Addon / Asset Discovery | Asset Store | READ: Project Foundations → Export Builds. Asset Store replaces Asset Library. | Beta store UI — verify licensing per addon |
| Agent Eyes / Visual QA | Capture → WebP → Rubric | READ: 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。不要加载类型或平台参考文档。 | 启动快,但存在意大利面式代码风险 |
| 复杂 RPG | Component-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 较重 |
| 模拟/RTS | Batch 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/视觉 QA | Capture → 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":
| Type | When to Use | Cost | Expert Use Case |
|---|---|---|---|
| Custom data structures, manual memory management | Lightest. Must call | Custom spatial hash maps, ECS-like data stores |
| Transient data packets, logic objects that auto-delete | Auto-deleted when no refs remain. | |
| Serializable data with Inspector support | Slightly heavier than RefCounted. Handles | |
| Needs | Heaviest — SceneTree overhead per node. | Only for entities that need per-frame updates or spatial transforms |
The expert pattern: Use subclasses for all logic packets and data containers. Reserve for things that must exist in the spatial tree. This halves scene tree overhead for complex systems.
RefCountedNode这是影响最大的专家级决策之一。Godot 文档明确指出应“避免将 Node 用于一切”:
| 类型 | 使用时机 | 成本 | 专家用例 |
|---|---|---|---|
| 自定义数据结构、手动内存管理 | 最轻量。必须手动调用 | 自定义 spatial hash map、类 ECS 数据存储 |
| 临时数据包、无引用后自动删除的逻辑对象 | 无引用后自动删除。 | |
| 可序列化且支持 Inspector 的数据 | 略重于 RefCounted。支持 | |
| 需要 | 最重——每个节点都有 SceneTree 开销。 | 仅用于需要逐帧更新或空间变换的实体 |
专家模式:所有逻辑数据包和数据容器都使用 子类。仅将 保留给必须存在于空间树中的对象。这可使复杂系统的场景树开销减半。
RefCountedNode🔧 Part 3: Core Workflows
🔧 第 3 部分:核心工作流
Workflow 1: Professional Scaffolding
工作流 1:专业脚手架
From empty project to production-ready container.
MANDATORY — READ ENTIRE FILE: Foundations
- Organize by Feature (,
/features/player/), not by class type. A/features/combat/folder contains the scene, script, resources, and tests for the player.player/ - READ: Signal Architecture — Create autoload with < 15 events.
GlobalSignalBus - READ: GDScript Mastery — Enable warning in Project Settings → GDScript → Debugging.
untyped_declaration - Apply Project Templates for base , export presets, and input map.
.gitignore - Use Builder (,
create_scene.py,add_node.py) to generate scene hierarchies programmatically via the Godot CLI.save_scene.py
[!CAUTION] Workflow 1 NEVER List
- NEVER use
paths in logic scripts. Useres://or@export_fileto ensure resources remain valid when moved.@export_dir- NEVER initialize children in
. The scene tree isn't ready. Use_init()or_ready().@onready- NEVER keep "Default" project settings for
. Set to 60 for consistency, or usePhysics Ticksfor adaptive logic.Engine.physics_ticks_per_second- NEVER use
inprint()for debugging; use the_process()orDebuggerto avoid frame-time spikes.push_error()
Do NOT load combat, multiplayer, genre, or platform references during scaffolding.
从空项目到可用于生产的项目容器。
必须完整读取:Foundations
- 按功能组织项目(、
/features/player/),而不是按类类型组织。/features/combat/目录应包含 Player 的场景、脚本、资源和测试。player/ - 读取:Signal Architecture——创建包含少于 15 个事件的 Autoload。
GlobalSignalBus - 读取:GDScript Mastery——在 Project Settings → GDScript → Debugging 中启用 警告。
untyped_declaration - 应用 Project Templates,生成基础 、导出预设和输入映射。
.gitignore - 使用 Builder(、
create_scene.py、add_node.py),通过 Godot CLI 以程序方式生成场景层级。save_scene.py
[!CAUTION] 工作流 1 禁止事项
- 逻辑脚本中绝不使用
路径。使用res://或@export_file,确保资源移动后仍然有效。@export_dir- 绝不在
中初始化子节点。此时场景树尚未就绪,应使用_init()或_ready()。@onready- 绝不保留“Default”项目的
设置。将其设为 60 以保持一致,或使用Physics Ticks实现自适应逻辑。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 , never handles input directly. This allows AI/Player swap with zero refactoring.
InputComponent - The State Machine ONLY handles transitions. Logic belongs in Components. tells
MoveStateto act, not the other way around.MoveComponent - 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
. If the parent changes, the entity breaks. Emit a signalparent.do_thing()instead.request_action- NEVER use
for movement. Use_processto avoid jitter on variable-refresh-rate monitors._physics_process- NEVER hardcode animation names. Use a
constant or aStringNamemap to enable easy renaming inResource.AnimationPlayer- NEVER use
with absolute paths. Useget_node()to survive tree refactoring.%UniqueName
构建模块化、可测试的角色。
必须完整读取:Composition → State Machine → CharacterBody2D 或 Physics 3D → Animation Tree
实体开发期间,不要加载 UI、Audio 或 Save/Load 参考文档。
- State Machine 应查询 ,而绝不直接处理输入。这样可以在无需重构的情况下切换 AI/Player。
InputComponent - State Machine 只负责状态转换。逻辑属于 Components。指示
MoveState执行动作,而不是反过来。MoveComponent - 每个实体都必须通过 F6 测试:按“Run Current Scene”(F6)时不得崩溃。如果崩溃,说明实体存在场景外依赖。
[!CAUTION] 工作流 2 禁止事项
- 绝不调用
。如果父节点发生变化,实体就会失效。应发出parent.do_thing()signal。request_action- 绝不使用
进行移动。使用_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 extending
ItemData.gd. Instantiate it as 100Resourcefiles instead of 100 scripts..tres - The HUD NEVER references the Player directly. It listens for on the Signal Bus.
player_health_changed - Enable "Local to Scene" on ALL variables, or call
@export Resourceinresource.duplicate(). Failure to do this is Bug #1 in Part 8._ready()
[!CAUTION] Workflow 3 NEVER List
- NEVER pass
references in a Signal Bus. Objects get freed; RIDs or IDs are safer for long-term tracking.Node- NEVER modify a
file at runtime via code (it modifies the disk file). Always.tresbefore modifying..duplicate()- NEVER use
for high-frequency search. UseArraywithDictionarykeys for O(1) lookups.StringName- NEVER use
for item counts or precise resource tracking; usefloatand scale for display.int
通过 Resource 连接战斗、背包和属性系统。
必须完整读取:Resource Patterns → RPG Stats → Combat → Inventory
- 创建一个继承 的
Resource。将其实例化为 100 个ItemData.gd文件,而不是编写 100 个脚本。.tres - HUD 绝不直接引用 Player。它应监听 Signal Bus 上的 。
player_health_changed - 对所有 变量启用“Local to Scene”,或在
@export Resource中调用_ready()。未处理此问题是第 8 部分中的 Bug #1。resource.duplicate()
[!CAUTION] 工作流 3 禁止事项
- 绝不在 Signal Bus 中传递
引用。对象可能被释放;长期跟踪应使用 RID 或 ID。Node- 绝不在运行时通过代码修改
文件,因为这会修改磁盘文件。修改前始终先调用.tres。.duplicate()- 绝不使用
执行高频搜索。使用以Array为键的StringName,实现 O(1) 查找。Dictionary- 绝不使用
表示物品数量或精确资源追踪;使用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
orObjectinstances. They contain transient pointers. Extract data into aNodeor customDictionary.Resource- NEVER use
for data that needs strict typing (e.g.,JSON). UseVector2orvar_to_bytesfor structured Godot types.ConfigFile- NEVER block the main thread for auto-saves. Use a
orThreadto serialize large dictionaries.WorkerThreadPool- NEVER save to
in an exported project; strictly useres://for persistent data.user://
必须读取: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处理结构化 Godot 类型。ConfigFile- 绝不在主线程上阻塞执行自动保存。使用
或Thread序列化大型字典。WorkerThreadPool- 绝不在导出项目中保存到
;持久化数据必须使用res://。user://
Workflow 5: Performance Optimization
工作流 5:性能优化
MANDATORY: Debugging/Profiling → Performance Optimization
Diagnosis-first approach (NEVER optimize blindly):
- High Script Time → Profile with built-in Profiler. Check if is being called on hundreds of nodes. Move to single-manager pattern or Server APIs (see Part 6).
_process - High Draw Calls → Use for repetitive geometry. Batch materials with ORM textures.
MultiMeshInstance - Physics Stutter → Simplify collisions to primitive shapes. Load 2D Physics or 3D Physics. Check if is used instead of
_processfor movement._physics_process - VRAM Overuse → Switch textures to VRAM Compression (BPTC/S3TC for desktop, ETC2 for mobile). Never ship raw PNG.
- Intermittent Frame Spikes → Usually GC pass, synchronous , or NavigationServer recalculation. Use
load().ResourceLoader.load_threaded_request()
[!CAUTION] Workflow 5 NEVER List
- NEVER use
insideget_nodes_in_group(). It's an O(n) operation every frame. Cache the array in_process._ready()- NEVER use
signals for "Stay" logic. UseArea2Dperiodically or a manager-levelget_overlapping_bodies()check.PhysicsServer- NEVER optimize before profiling. A 1ms script is irrelevant if you have 2000 draw calls killing the GPU.
- NEVER use
in hot paths; strictlyload()or usepreloadfor async loading.ResourceLoader
必须读取:Debugging/Profiling → Performance Optimization
采用诊断优先方式(绝不盲目优化):
- 脚本时间过高 → 使用内置 Profiler 进行分析。检查是否对数百个节点调用了 。改用单管理器模式或 Server API(参见第 6 部分)。
_process - Draw call 过高 → 对重复几何体使用 。使用 ORM texture 合并材质。
MultiMeshInstance - 物理卡顿 → 将碰撞体简化为基础形状。加载 2D Physics 或 3D Physics。检查移动是否错误地使用了 而非
_process。_physics_process - VRAM 使用过多 → 将 texture 切换为 VRAM Compression(桌面端使用 BPTC/S3TC,移动端使用 ETC2)。绝不发布原始 PNG。
- 间歇性帧峰值 → 通常由 GC 扫描、同步 或 NavigationServer 重算导致。使用
load()。ResourceLoader.load_threaded_request()
[!CAUTION] 工作流 5 禁止事项
- 绝不在
中调用_process。这是每帧 O(n) 操作,应在get_nodes_in_group()中缓存数组。_ready()- 绝不使用
signal 实现“Stay”逻辑。定期使用Area2D,或在管理器层级使用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 autoload that translates all input types into normalized actions. NEVER read
InputManagerdirectly — it blocks controller and touch support.Input.is_key_pressed() - Mobile touch targets: minimum 44px physical size. Use with Safe Area logic for notch/cutout devices.
MarginContainer - Web exports: Godot's requires user interaction before first play (browser policy). Handle this with a "Click to Start" screen.
AudioServer
[!CAUTION] Workflow 6 NEVER List
- NEVER use
for feature detection. UseOS.get_name()or custom feature tags to handle subsets like "SteamDeck."OS.has_feature("mobile")- NEVER assume a specific aspect ratio. Always use
orExpandin combinations withKeep Aspectnodes.Anchor- NEVER use desktop-only shaders (e.g., complex depth sampling) on Mobile/Web without a GLES3/Compatibility secondary path.
- NEVER ignore
for desktop builds; it ensures keyboard layouts (AZERTY/QWERTY) don't break movement.physical_keycode
- NEVER pass unsanitized strings to — Prevents script injection in web builds. Use a
JavaScriptBridge.eval()helper.sanitize_js_string()
必须读取:Input Handling → Adapt Desktop→Mobile → Platform Mobile
按需读取:Platform Desktop、Platform Web、Platform Console、Platform VR。
- 使用 Autoload,将所有输入类型转换为标准化 action。绝不直接读取
InputManager,否则会阻碍手柄和触控支持。Input.is_key_pressed() - 移动端触控目标:物理尺寸至少为 44px。在带刘海或挖孔的设备上,使用带 Safe Area 逻辑的 。
MarginContainer - Web 导出:根据浏览器策略,Godot 的 要求首次播放前发生用户交互。通过“Click to Start”画面处理此要求。
AudioServer
[!CAUTION] 工作流 6 禁止事项
- 绝不使用
进行功能检测。使用OS.get_name()或自定义 feature tag,以处理OS.has_feature("mobile")等子集。SteamDeck.- 绝不假定特定宽高比。始终将
或Expand与Keep Aspect节点结合使用。Anchor- 绝不在 Mobile/Web 上使用桌面端专用 shader(例如复杂的 depth sampling),除非提供 GLES3/Compatibility 次要路径。
- 绝不在桌面端构建中忽略
;它可确保 AZERTY/QWERTY 等键盘布局不会破坏移动操作。physical_keycode- 绝不将未净化的字符串传给
,以防止 Web 构建中的脚本注入。使用JavaScriptBridge.eval()辅助函数。sanitize_js_string()
Workflow 7: Procedural Generation
工作流 7:程序化生成
MANDATORY: Procedural Gen → Tilemap Mastery or 3D World Building → Navigation
- ALWAYS use resource with a fixed
FastNoiseLitefor deterministic generation.seed - 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 . Build the scene chunk off-tree, then
WorkerThreadPoolon the main thread.add_child.call_deferred()
[!CAUTION] Workflow 7 NEVER List
- NEVER instantiate nodes for "Background" noise. Use
or draw loops inMultiMeshInstancefor thousands of small details._draw- 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
. It stalls the physics thread.concave_polygon_shape- NEVER perform pathfinding queries every frame for all units. Use a
withNavigationAgentupdates on a timer.target_position
必须读取:Procedural Gen → Tilemap Mastery 或 3D World Building → Navigation
- 始终使用带固定 的
seedresource,以实现确定性生成。FastNoiseLite - 绝不在主线程上烘焙 NavMesh。使用 和
NavigationServer3D.parse_source_geometry_data()。NavigationServer3D.bake_from_source_geometry_data_async() - 对于无限世界:chunk 加载必须通过 在后台线程中执行。在树外构建场景 chunk,然后在主线程上调用
WorkerThreadPool。add_child.call_deferred()
[!CAUTION] 工作流 7 禁止事项
- 绝不为“Background”噪声实例化节点。对于数千个小细节,使用
或MultiMeshInstance绘制循环。_draw- 绝不因一项更改而重新生成整张地图。使用“Dirty Chunk”系统,仅更新实际发生变化的内容。
- 使用
时,绝不在与 mesh 生成相同的帧放置碰撞体,否则会阻塞物理线程。concave_polygon_shape- 绝不每帧对所有单位执行寻路查询。使用
,并通过定时器更新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.
- handles replication in Godot 4. Configure it per scene, not globally.
MultiplayerSpawner
[!CAUTION] Workflow 8 NEVER List
- NEVER trust
(Client to Server) without validation. A hacked client can sendrpc_id(1, ...).damage = 999999- NEVER replicate
transforms directly. Replicate_processvector and simulate movement on both sides.Input- NEVER use
for high-frequency packets (movement). UseTCP/UDPand handle dropped packets with interpolation.ENet- NEVER synchronize every projectile; use Client-Side Prediction for visuals and only RPC the "Fire" event.
- vs
ReflectionProbevsVoxelGI: Probes are cheap/static, VoxelGI is medium/baked, SDFGI is expensive/dynamic. Choose based on your platform budget (see Part 5).SDFGI
必须读取:Single→Multiplayer → Networking → Server Arch
不要加载单人类型蓝图。
- Client 发送 Input,Server 计算 Outcome。Client 绝不决定伤害、位置增量或背包变化。
- 使用带服务器校正的 Client-Side Prediction:在本地预测,再根据服务器快照进行校正。可隐藏最多约 150ms 的延迟。
- 在 Godot 4 中使用 处理复制。应按场景而非全局配置它。
MultiplayerSpawner
[!CAUTION] 工作流 8 禁止事项
- 绝不在未验证的情况下信任
(Client 到 Server)的数据。恶意客户端可以发送rpc_id(1, ...)。damage = 999999- 绝不直接复制
transform。应复制_process向量,并在双方模拟移动。Input- 绝不对高频数据包(如移动)使用
。使用TCP/UDP,并通过插值处理丢包。ENet- 绝不同步每一个 projectile;视觉效果使用 Client-Side Prediction,仅通过 RPC 传递“Fire”事件。
- 与
ReflectionProbe、VoxelGI的选择:Probes 成本低且静态,VoxelGI 成本中等且需烘焙,SDFGI 成本高且支持动态效果。应根据平台预算选择(参见第 5 部分)。SDFGI
Workflow 9: Responsive UI & Expert Theming (Audit Verified)
工作流 9:响应式 UI 与专家主题系统(已通过审计验证)
MANDATORY Chain: UI Containers → UI Theming → Rich Text → Tweening
- The F6 Principle: Every UI scene must be testable in isolation. Use only on the background,
MOUSE_FILTER_STOPon children.PASS - Breathing Room: Use over manual padding.
add_theme_constant_override("separation", X) - Adaptive Scaling: Use for breakpoint-aware mobile/desktop switching.
responsive_layout_builder.gd - Lifecycle Safety: Never scroll to a new child on the same frame. before modifying
await get_tree().process_frame.scroll_vertical - Data Integration: Use binding; UI nodes MUST be stateless projection layers.
Resource-to-UI
[!CAUTION] Workflow 9 NEVER List
- NEVER use absolute pixel offsets. UI becomes unreadable on 4K or tiny mobile screens. Use
sizing.Container- NEVER deep-nest
. It makes the Inspector unusable. Use a singleMarginContainersresource for project-wide margins.Theme- NEVER connect UI buttons to gameplay logic directly. UI sends "Signal",
listens. This prevents UI-deletion crashes.PlayerController- NEVER use
to move a UI element to a target. Use a_process()to avoid stuttering and frame-rate dependence.Tween- NEVER leave
asmouse_filteron transparent containers; it "eats" clicks for everything behind it.STOP
- NEVER use dynamic on paths without validating the
load()prefix and safe extension (res://,.tres,.res) — Prevents arbitrary code/resource execution..theme
必须依次读取:UI Containers → UI Theming → Rich Text → Tweening
- F6 原则:每个 UI 场景都必须能够独立测试。仅在背景上使用 ,在子节点上使用
MOUSE_FILTER_STOP。PASS - 留白:使用 ,而不是手动设置 padding。
add_theme_constant_override("separation", X) - 自适应缩放:使用 实现基于断点的移动端/桌面端切换。
responsive_layout_builder.gd - 生命周期安全:绝不在同一帧滚动到新的子节点。修改 前先
scroll_vertical。await get_tree().process_frame - 数据集成:使用 绑定;UI 节点必须是无状态投影层。
Resource-to-UI
[!CAUTION] 工作流 9 禁止事项
- 绝不使用绝对像素偏移。UI 在 4K 或小型移动屏幕上会变得不可读。应使用
调整尺寸。Container- 绝不深层嵌套
,否则 Inspector 将难以使用。项目范围的 margin 应使用单一MarginContainerresource 管理。Theme- 绝不将 UI 按钮直接连接到游戏逻辑。UI 应发送“Signal”,由
监听,从而避免删除 UI 后引发崩溃。PlayerController- 绝不使用
移动 UI 元素。应使用_process(),避免卡顿和帧率依赖。Tween- 绝不让透明容器的
保持为mouse_filter,否则它会“吞掉”后方所有元素的点击。STOP- 绝不对未验证
前缀及安全扩展名(res://、.tres、.res)的路径执行动态.theme,以防止任意代码或 resource 执行。load()
Workflow 10: Cinematic Lighting & VFX (Audit Verified)
工作流 10:电影级光照与 VFX(已通过审计验证)
MANDATORY Chain: 3D Lighting → Particles → 3D Materials → Shaders
- The GI Choice: VoxelGI for interiors, SDFGI for open world. Never ship with both overlapping.
- Shadow Budget: Max 2 Shadow-casting DirectionalLights. Use for mobile fills.
fake_gi_bounce.gd - VFX Lifecycle: Use signal over Timers. Re-run with
finishedto avoid async GPU stalls.restart() - Optimization: Use packing (AO/Rough/Metal) to save GPU cache and texture slots.
ORM Texture - Batching: Use for material variations across thousands of instances without draw call penalties.
Instance Uniforms
[!CAUTION] Workflow 10 NEVER List
- NEVER scale
nodes; strictly scale the Shape Resource to avoid physics jitter.CollisionShape- NEVER use
for cutout meshes (leaves/fences); useTRANSPARENCY_ALPHAto prevent sorting artifacts.ALPHA_SCISSOR- 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
andDirectionalLight2D.CanvasModulate- NEVER ignore
near/far planes; improper settings cause Z-fighting in large worlds.Camera3D
必须依次读取:3D Lighting → Particles → 3D Materials → Shaders
- GI 选择:室内场景使用 VoxelGI,开放世界使用 SDFGI。绝不让二者重叠并同时发布。
- 阴影预算:最多使用 2 个投射阴影的 DirectionalLight。移动端补光使用 。
fake_gi_bounce.gd - VFX 生命周期:使用 signal,而非 Timer。通过
finished重新运行,避免异步 GPU 卡顿。restart() - 优化:使用 打包(AO/Rough/Metal),节省 GPU 缓存和 texture slot。
ORM Texture - 批处理:使用 为数千个实例创建材质变化,而不增加 draw call 惩罚。
Instance Uniforms
[!CAUTION] 工作流 10 禁止事项
- 绝不缩放
节点;应严格缩放 Shape Resource,以避免物理抖动。CollisionShape- 对 cutout mesh(树叶、围栏)绝不使用
;使用TRANSPARENCY_ALPHA防止排序伪影。ALPHA_SCISSOR- 游戏过程中绝不动画 CSG 节点,否则会强制执行昂贵的 CPU 几何体重算。
- 对于 2D 风格游戏,绝不使用实时 Global Illumination(SDFGI/VoxelGI)。应使用
和DirectionalLight2D。CanvasModulate- 绝不忽略
的 near/far plane;设置不当会导致大型世界中的 Z-fighting。Camera3D
Workflow 11: Programmatic Scene Building (Builder)
工作流 11:程序化场景构建(Builder)
MANDATORY: Builder
Use ONLY for batch operations or complex procedural scaffolds. Prefer the standalone skill when doing heavy CLI automation.
godot-builder- Step 1: Draft the node hierarchy on paper/markdown before touching disk.
- Step 2: Use to define the root node and
create_scene.pypath..tscn - Step 3: Use for children. Set
add_node.pyon every node so serialization keeps them.owner - Step 4: ALWAYS call or
run_project.pyto verify the scene loads cleanly.launch_editor.py - 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
without designing the hierarchy first — spaghetti scenes follow.add_node.py- NEVER use absolute filesystem paths in scripts or scene props; use
only.res://- NEVER add a
/CollisionShape2Dwithout assigning a Shape resource — the node alone does nothing.CollisionShape3D- NEVER skip verification via
/run_project.pyafter batch scene writes.launch_editor.py
必须读取:Builder
仅用于批处理操作或复杂的程序化脚手架。执行繁重的 CLI 自动化时,优先使用独立的 skill。
godot-builder- 步骤 1:接触磁盘之前,先在纸面或 markdown 中设计节点层级。
- 步骤 2:使用 定义根节点和
create_scene.py路径。.tscn - 步骤 3:使用 添加子节点。为每个节点设置
add_node.py,确保序列化时保留它们。owner - 步骤 4:始终调用 或
run_project.py,验证场景能够干净加载。launch_editor.py - 专家规则:使用 Builder 构建结构(节点、名称、继承关系),再使用 GDScript 构建行为。
[!CAUTION] 工作流 11 禁止事项
- 绝不在设计层级之前直接调用
,否则会产生意大利面式场景。add_node.py- 脚本或场景属性中绝不使用绝对文件系统路径;只能使用
。res://- 添加
/CollisionShape2D时,绝不不分配 Shape resource;仅添加节点不会产生任何效果。CollisionShape3D- 批量写入场景后,绝不跳过通过
/run_project.py进行的验证。launch_editor.py
Security: Boundary Markers & Validation
安全:边界标记与验证
When agents ingest untrusted scene/data text before writing files:
- Boundary Markers: Wrap analysis in and
<<<CONTEXT_START>>>.<<<CONTEXT_END>>> - Sanitization: Node names must be alphanumeric/underscored. Paths must start with .
res:// - Verification: Confirm scene existence before modification.
当 Agent 在写入文件前摄取不可信的场景或数据文本时:
- 边界标记:使用 和
<<<CONTEXT_START>>>包裹分析内容。<<<CONTEXT_END>>> - 净化:节点名称只能包含字母、数字和下划线。路径必须以 开头。
res:// - 验证:修改前确认场景存在。
🚫 Part 4: The Expert NEVER List
🚫 第 4 部分:专家禁止事项清单
Each rule includes the non-obvious reason — the thing only shipping experience teaches.
- NEVER use — Absolute paths break when ANY ancestor is renamed or reparented. Use
get_tree().root.get_node("..."),%UniqueNames, or signal-based discovery.@export NodePath - NEVER use inside a loop or
load()— Synchronous disk read blocks the ENTIRE main thread. Use_processat script top for small assets,preload()for large ones.ResourceLoader.load_threaded_request() - NEVER while external references exist — Parent nodes or arrays holding refs will get "Deleted Object" errors. Clean up refs in
queue_free()and set them to_exit_tree()before freeing.null - NEVER put gameplay logic in —
_draw()is called on the rendering thread. Mutating game state causes race conditions with_draw()._physics_process - NEVER use for 1000+ overlapping objects — Each overlap check has O(n²) broadphase cost. Use
Area2D,ShapeCast2D, or Server APIs for bullet-hell patterns.PhysicsDirectSpaceState2D.intersect_shape() - NEVER mutate external state from a component — If calls
HealthComponent, deleting the HUD crashes the game. Components emit signals; listeners decide how to respond.$HUD.update_bar() - NEVER use in
await—_physics_processyields execution, meaning the physics step skips frames. Move async operations to a separate method triggered by a signal.await - NEVER use keys in hot-path dictionary lookups — String hashing is O(n). Use
String(StringName) for O(1) pointer comparisons, or integer enums.&"key" - NEVER store references to freed objects — Crashes silently or throws errors. Disconnect signals in
Callableor use_exit_tree().CONNECT_ONE_SHOT - NEVER use for 1000+ entities — Each
_processcall has per-node SceneTree overhead. Use a single_processthat iterates an array of data structs (Data-Oriented pattern), or use Server APIs directly.Manager._process - NEVER use on a node that may be freed — If a node is
Tween'd while a Tween runs, it errors. Kill tweens inqueue_free()or bind to SceneTree:_exit_tree().get_tree().create_tween() - NEVER request data FROM or
RenderingServerinPhysicsServer— 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._process - NEVER use 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
call_deferred().@onready - 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.
- NEVER let inheritance exceed 3 levels — Beyond 3, debugging chains is a nightmare. Use composition (
super()children) to add behaviors instead.Node - NEVER use for hit detection or movement in physics-heavy genres (FPS/ARPG); strictly use
_processto ensure frame-independent collision detection._physics_process - NEVER trust the client for authority on persistent game state (Health, XP, Inventory). Handled exclusively via Server-Auth or Secure Checksums.
- NEVER use standard strings for high-frequency runtime checks; strictly use (&"active") to avoid O(n) hashing.
StringName - NEVER manually handle RVO avoidance every frame in unit-heavy games (RTS/MOBA); offload to internal threading.
NavigationAgent - NEVER block the main thread for procedural generation or heavy I/O; strictly offload to .
WorkerThreadPool - NEVER ignore on Resources used in unique instances (e.g. enemy stats); failure causes shared-memory bugs across all instances.
Local-to-Scene - NEVER use for currency; strictly use Integer Cents to avoid precision drift in complex economies.
float - NEVER set before
target_position; navigation maps are not ready duringphysics_frame._ready() - NEVER use or
TRANSPARENCY_HASHfor large cutout surfaces (foliage); useALPHAfor performance and sorting.ALPHA_SCISSOR - NEVER scale nodes (Node2D/3D scale) — Use shape handles or resize the resource to avoid unpredictable physics normals and jitter.
CollisionShape - NEVER apply gravity while is true — Causes micro-jitter and prevents floor-snapping; strictly reset vertical velocity to 0 or a small constant.
is_on_floor() - NEVER forget to disconnect dynamic signals (Capturing Lambdas) — Godot cannot auto-disconnect lambdas that capture local variables; they will cause crashes on freed objects.
- NEVER use mouse events for mobile touch — Strictly use and
InputEventScreenTouchfor reliable multi-touch support.InputEventScreenDrag - NEVER use Forward+ renderer for mobile — Strictly use Mobile or Compatibility renderers to avoid GPU bottlenecks and battery drain.
- NEVER accumulate mouse rotation directly on Transforms — Strictly store separate Yaw/Pitch variables to prevent gimbal lock and precision loss.
- NEVER use standard Strings for high-frequency runtime checks — Strictly use (&"active") to avoid O(n) hashing overhead.
StringName - NEVER trust the client for game state (Health, Inventory) — Clients suggest actions; Server validates and broadcasts to prevent cheating.
- NEVER use RPCs for movement updates — Use
Reliableto prevent Head-of-Line blocking in high-latency scenarios.UnreliableOrdered
每条规则都包含不显而易见的深层原因——这是实际交付经验才能传授的知识。
- 绝不使用 ——只要任意祖先被重命名或重新设置父节点,绝对路径就会失效。使用
get_tree().root.get_node("...")、%UniqueNames或基于 signal 的发现机制。@export NodePath - 绝不在循环或 中使用
_process——同步磁盘读取会阻塞整个主线程。小型 asset 应在脚本顶部使用load(),大型 asset 应使用preload()。ResourceLoader.load_threaded_request() - 当外部引用仍存在时,绝不调用 ——父节点或持有引用的数组会导致“Deleted Object”错误。在
queue_free()中清理引用,并在释放前将其设为_exit_tree()。null - 绝不将游戏逻辑放在 中——
_draw()会在渲染线程上调用。修改游戏状态会与_draw()产生竞态条件。_physics_process - 绝不对 1,000+ 个重叠对象使用 ——每次重叠检测都有 O(n²) broadphase 成本。对于 bullet-hell 模式,使用
Area2D、ShapeCast2D或 Server API。PhysicsDirectSpaceState2D.intersect_shape() - 绝不从组件修改外部状态——如果 调用
HealthComponent,删除 HUD 就会使游戏崩溃。组件应发出 signal,由监听者决定如何响应。$HUD.update_bar() - 绝不在 中使用
_physics_process——await会产生执行权移交,导致物理步跳过帧。将异步操作移到由 signal 触发的独立方法中。await - 绝不在热点 Dictionary 查找中使用 键——String 哈希为 O(n)。使用
String(StringName)进行 O(1) 指针比较,或使用整数枚举。&"key" - 绝不保存指向已释放对象的 引用——这会静默崩溃或抛出错误。在
Callable中断开 signal,或使用_exit_tree()。CONNECT_ONE_SHOT - 绝不对 1,000+ 实体使用 ——每次
_process调用都有逐节点 SceneTree 开销。使用单个_process遍历数据结构数组(Data-Oriented 模式),或直接使用 Server API。Manager._process - 绝不在可能被释放的节点上使用 ——如果节点在 Tween 运行期间被
Tween,就会出错。在queue_free()中终止 Tween,或绑定到 SceneTree:_exit_tree()。get_tree().create_tween() - 绝不在 中向
_process或RenderingServer请求数据——这些服务器异步运行。调用 getter 会强制同步等待,严重损害性能。这些 API 在热点路径中被有意设计为只写。PhysicsServer - 绝不将 当作初始化顺序问题的临时补救措施——它会掩盖架构问题(对树顺序的依赖)。应使用显式初始化 signal 或
call_deferred()修复实际依赖关系。@onready - 绝不创建循环 signal 连接——Node A 连接 Node B,Node B 又连接 Node A。第一次 emit 就会产生无限循环。使用中介者模式(Signal Bus)打破循环。
- 绝不让继承层级超过 3 层——超过 3 层后,调试 调用链会非常困难。应使用组合(
super()子节点)添加行为。Node - 在物理密集类型(FPS/ARPG)中,绝不使用 进行命中检测或移动;严格使用
_process,确保碰撞检测与帧率无关。_physics_process - 绝不在持久游戏状态(Health、XP、Inventory)上信任客户端权威。只能通过 Server-Auth 或 Secure Checksums 处理。
- 绝不在高频运行时检查中使用普通 String;严格使用 (
StringName),避免 O(n) 哈希。&"active" - 绝不在单位密集型游戏(RTS/MOBA)中每帧手动处理 RVO 避让;应交给 的内部线程处理。
NavigationAgent - 绝不阻塞主线程执行程序化生成或繁重 I/O;严格将其卸载到 。
WorkerThreadPool - 绝不忽略唯一实例所用 Resource 的 (例如 enemy stats);否则会在所有实例间产生共享内存 Bug。
Local-to-Scene - 绝不使用 表示货币;严格使用整数美分,避免复杂经济系统中的精度漂移。
float - 绝不在 之前设置
physics_frame;target_position期间 navigation map 尚未就绪。_ready() - 绝不对大型 cutout 表面(树叶)使用 或
TRANSPARENCY_HASH;使用ALPHA提升性能并改善排序。ALPHA_SCISSOR - 绝不缩放 节点(Node2D/3D scale)——应调整 handle 或调整 resource 尺寸,以避免不可预测的 physics normal 和抖动。
CollisionShape - 绝不在 为 true 时施加重力——这会造成微抖动并阻止地面吸附;应将垂直速度严格重置为 0 或一个很小的常量。
is_on_floor() - 绝不忘断开捕获 Lambda 的动态 signal——Godot 无法自动断开捕获局部变量的 Lambda;它们会在对象释放后导致崩溃。
- 绝不为移动端触控使用鼠标事件——严格使用 和
InputEventScreenTouch,以可靠支持多点触控。InputEventScreenDrag - 绝不在移动端使用 Forward+ renderer——严格使用 Mobile 或 Compatibility renderer,以避免 GPU 瓶颈和电量消耗。
- 绝不直接在 Transform 上累积鼠标旋转——应分别存储 Yaw/Pitch,以避免万向节锁和精度损失。
- 绝不在高频运行时检查中使用普通 String——严格使用 (
StringName),避免 O(n) 哈希开销。&"active" - 绝不在游戏状态(Health、Inventory)上信任客户端——Client 仅建议动作,由 Server 验证和广播,以防止作弊。
- 绝不使用 RPC 传输移动更新——使用
Reliable,避免高延迟场景中的 Head-of-Line Blocking。UnreliableOrdered
📊 Part 5: Performance Budgets (Concrete Numbers)
📊 第 5 部分:性能预算(具体数值)
| Metric | Mobile Target | Desktop Target | Expert Note |
|---|---|---|---|
| Draw Calls | < 100 (2D), < 200 (3D) | < 500 | |
| Triangle Count | < 100K visible | < 1M visible | LOD system mandatory above 500K |
| Texture VRAM | < 512MB | < 2GB | VRAM Compression: ETC2 (mobile), BPTC (desktop) |
| Script Time | < 4ms per frame | < 8ms per frame | Move hot loops to Server APIs |
| Physics Bodies | < 200 active | < 1000 active | Use |
| Particles | < 2000 total | < 10000 total | GPU particles, set |
| Audio Buses | < 8 simultaneous | < 32 simultaneous | Use Audio Systems bus routing |
| Save File Size | < 1MB | < 50MB | Seed + Delta pattern for procedural worlds |
| Scene Load Time | < 500ms | < 2s | |
| 指标 | 移动端目标 | 桌面端目标 | 专家说明 |
|---|---|---|---|
| Draw Calls | < 100(2D),< 200(3D) | < 500 | 树叶/碎片使用 |
| 三角形数量 | < 100K 可见 | < 1M 可见 | 超过 500K 时必须使用 LOD 系统 |
| Texture VRAM | < 512MB | < 2GB | VRAM Compression:移动端 ETC2,桌面端 BPTC |
| 脚本时间 | 每帧 < 4ms | 每帧 < 8ms | 将热点循环迁移至 Server API |
| 物理刚体 | < 200 个活跃 | < 1000 个活跃 | 大规模模拟直接使用 |
| Particles | 总计 < 2000 | 总计 < 10000 | 使用 GPU particles,并手动设置 |
| Audio Buses | 同时 < 8 | 同时 < 32 | 使用 Audio Systems 的 bus routing |
| 存档大小 | < 1MB | < 50MB | 程序化世界使用 Seed + Delta 模式 |
| 场景加载时间 | < 500ms | < 2s | 使用 |
⚙️ 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 with RIDs instead of
RenderingServer/Sprite2Dnodes.MeshInstance3D - Bullet-hell / particle systems with script interaction: Use body creation instead of
PhysicsServer2Dnodes.Area2D - Mass physics simulation: Use directly for ragdoll fields, debris, or fluid-like simulations.
PhysicsServer3D
- 10K+ 渲染实例(sprite、mesh):使用带 RID 的 ,而不是
RenderingServer/Sprite2D节点。MeshInstance3D - 需要脚本交互的 Bullet-hell/粒子系统:使用 创建刚体,而不是
PhysicsServer2D节点。Area2D - 大规模物理模拟:直接使用 实现 ragdoll 场、碎片或类流体模拟。
PhysicsServer3D
📊 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| Metric | SceneTree (Nodes) | Server APIs (RIDs) | Expert Rationale |
|---|---|---|---|
| Object Limit | ~1,000 - 5,000 | 50,000+ | SceneTree has O(n) traversal costs; Servers use O(1) direct RID handles. |
| Memory Overhead | ~2KB - 10KB per Node | < 200 bytes per RID | Nodes carry tree state, signals, and inspector metadata. RIDs are opaque 24-byte handles. |
| CPU Time | High (Virtual calls) | Minimal (Direct API) | Nodes must call |
| Threading | Main Thread Only | Inherently Thread-Safe | Most Server APIs are thread-safe (must be enabled in Project Settings). |
| Garbage Collection | Automatic (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 传播和 等虚拟函数调用带来的沉重 CPU 开销。
_process| 指标 | SceneTree(Nodes) | Server API(RIDs) | 专家原理 |
|---|---|---|---|
| 对象上限 | 约 1,000 - 5,000 | 50,000+ | SceneTree 有 O(n) 遍历成本;Server 使用 O(1) 的直接 RID handle。 |
| 内存开销 | 每个 Node 约 2KB - 10KB | 每个 RID < 200 bytes | Node 携带树状态、signal 和 Inspector 元数据;RID 是不透明的 24-byte handle。 |
| CPU 时间 | 高(虚函数调用) | 极低(直接 API) | 每个实例都必须由 Node 调用 |
| 线程处理 | 仅限主线程 | 天然线程安全 | 多数 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
undefinedServer API 通过 RID(Resource ID)通信——它是服务器端对象的不透明 handle。关键规则:
gdscript
undefinedCreate 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)
undefinedvar texture: Texture2D = preload("res://sprite.png")
RenderingServer.canvas_item_add_texture_rect(ci_rid, Rect2(-texture.get_size() / 2, texture.get_size()), texture)
undefinedThreading 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 to attach them to the live tree.
add_child.call_deferred() - GDScript Dictionaries/Arrays: reads and writes across threads are safe, but resizing (append, erase, resize) requires a .
Mutex - NEVER load the same from multiple threads simultaneously — use one loading thread.
Resource
- 场景树不是线程安全的。但启用 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 陷阱(资深用户专属)
- Resources are shared by default: Multiple scene instances ALL share the same
@export. UseResourceinresource.duplicate()or enable "Local to Scene" checkbox. This is the #1 most reported Godot 4 bug by newcomers._ready() - Signal syntax silently fails: (Godot 3 syntax) compiles but does nothing in Godot 4. Must use
connect("signal_name", target, "method").signal_name.connect(callable) - is no longer a Node: Created via
Tween, bound to the creating node's lifetime. If that node is freed, the Tween dies. Usecreate_tween()for persistent tweens.get_tree().create_tween() - layers vs masks:
PhysicsBody= "what I am".collision_layer= "what I scan for". Setting both to the same value causes self-collision or missed detections.collision_mask - vs
StringNamein hot paths:String(StringName) uses pointer comparison (O(1)).&"key"uses character comparison (O(n)). Always useStringfor dictionary keys inStringName._process - timing: Runs AFTER
@onreadybut DURING_init(). If you need constructor-time setup, use_ready(). If you need tree access, use_init()or@onready. Mixing them causes nulls._ready() - Server query stalls: Calling or
RenderingServergetter functions inPhysicsServerforces a synchronous pipeline flush. These servers run async — requesting data from them stalls the entire pipeline until the server catches up._process - API change: Returns
move_and_slide()(whether collision occurred). Velocity is now a property, not a parameter.boolbefore callingvelocity = dir * speed.move_and_slide()
- Resource 默认共享:多个场景实例会共享同一个
@export。在Resource中使用_ready(),或启用“Local to Scene”复选框。这是 Godot 4 新手反馈最多的 Bug #1。resource.duplicate() - Signal 语法会静默失效:(Godot 3 语法)虽然能编译,但在 Godot 4 中不会执行任何操作。必须使用
connect("signal_name", target, "method")。signal_name.connect(callable) - 不再是 Node:通过
Tween创建,并绑定到创建它的节点生命周期。如果该节点被释放,Tween 也会消失。对于持久 Tween,使用create_tween()。get_tree().create_tween() - PhysicsBody 的 layer 与 mask:表示“我是什么”,
collision_layer表示“我检测什么”。将两者设为相同值会导致自碰撞或漏检。collision_mask - 热点路径中的 与
StringName:String(StringName)使用指针比较(O(1));&"key"使用字符比较(O(n))。在String中,Dictionary 键始终使用_process。StringName - 时序:它在
@onready之后、_init()期间运行。如果需要构造时初始化,使用_ready();如果需要访问场景树,使用_init()或@onready。混用会导致空值。_ready() - Server 查询卡顿:在 中调用
_process或RenderingServergetter 会强制同步刷新 pipeline。这些服务器异步运行;在PhysicsServer中请求数据会使整个 pipeline 停滞,直到服务器完成追赶。_process - API 变化:返回
move_and_slide()(是否发生碰撞)。Velocity 现在是属性,而不是参数。调用bool前先设置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: property → → parent wrong layer → → behind camera's clip (3D) → not set → not in any (renders behind everything).
visiblez_indexCanvasLayermodulate.a == 0nearSubViewport.render_target_update_modeCanvasItemCanvasLayer症状:节点存在于场景树中,但没有显示。
专家诊断链: 属性 → → 父级 层级错误 → → 位于相机 裁剪面之后(3D)→ 未设置 → 不属于任何 (渲染在其他内容之后)。
visiblez_indexCanvasLayermodulate.a == 0nearSubViewport.render_target_update_modeCanvasItemCanvasLayerThe "Input Eaten" Bug
“输入被吞掉”Bug
Symptom: Clicks or key presses ignored intermittently.
Expert diagnosis: Another node with overlapping the target. Or, modal consuming unhandled input. Or, in another script calling .
Controlmouse_filter = STOPPopupMenu_unhandled_input()get_viewport().set_input_as_handled()症状:点击或按键偶尔被忽略。
专家诊断:另一个 节点的 与目标重叠;或模态 消费了未处理输入;或另一个脚本中的 调用了 。
Controlmouse_filter = STOPPopupMenu_unhandled_input()get_viewport().set_input_as_handled()The "Physics Jitter" Bug
“物理抖动”Bug
Symptom: Character vibrates at surface contacts.
Expert diagnosis: too large. Or, used for movement instead of (interpolation mismatch). Or, collision shapes overlap at spawn (push each other apart permanently).
Safe Margin_process_physics_process症状:角色在表面接触时振动。
专家诊断: 过大;或移动时使用 而非 ,导致插值不匹配;或碰撞形状在生成时相互重叠,从而持续互相排斥。
Safe Margin_process_physics_processThe "Memory Leak"
“内存泄漏”
Symptom: RAM grows steadily during play.
Expert diagnosis: called but reference held in Array/Dictionary. Or, signals connected with without cleanup. Use Profiler "Objects" tab to find orphaned instances. Search for instances without a parent.
queue_free()CONNECT_REFERENCE_COUNTEDNode症状:游戏过程中 RAM 持续增长。
专家诊断:调用了 ,但 Array/Dictionary 中仍持有引用;或使用 连接 signal 后未清理。使用 Profiler 的“Objects”标签查找孤立实例,并搜索没有父节点的 实例。
queue_free()CONNECT_REFERENCE_COUNTEDNodeThe "Frame Spike"
“帧峰值”
Symptom: Smooth FPS but periodic drops.
Expert diagnosis: GDScript GC pass. Or, synchronous for a large resource. Or, rebaking. Or, Server API query stall (requesting data from in ). Profile with built-in Profiler → look for function-level spikes.
load()NavigationServerRenderingServer_process症状:FPS 平稳,但周期性下降。
专家诊断:GDScript GC 扫描;同步 大型 resource; 重新烘焙;或 Server API 查询停顿(在 中向 请求数据)。使用内置 Profiler 定位函数级峰值。
load()NavigationServer_processRenderingServer🚀 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 is a container for . In Godot, everything is a Node.
GameObjectComponents- Unity: +
GameObject+Transform+MeshFilter.Script - Godot: A node (which is a Transform and a Mesh) with a script attached.
MeshInstance3D - Expert Shift: Use Node composition. If you need a "Health Component", add a or
Nodeas a child called "Health". UseArea3Dfor logic-only components to save memory.RefCounted
在 Unity 中, 是 的容器。而在 Godot 中,一切都是 Node。
GameObjectComponents- Unity:+
GameObject+Transform+MeshFilter。Script - Godot:节点(它本身就是 Transform 和 Mesh)并附加脚本。
MeshInstance3D - 专家思维转变:使用 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 file. This promotes "Post-Order Traversal" (children are ready before parents).
.tscn
Godot 没有单独的“Prefab”概念,因为每个场景都是 Prefab。
- 可以在另一个场景中无限嵌套实例化场景。
- 专家思维转变:每个可复用系统(Player、Enemy、UI Button)都应是独立的 文件。这有助于采用“Post-Order Traversal”(子节点先于父节点就绪)。
.tscn
3. Signals vs. Events/Actions
3. Signal 与 Event/Action
Godot's system is a native implementation of the Observer pattern.
Signal- 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 的 系统是 Observer 模式的原生实现。
Signal- 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 () to gain compilation speedups and editor completion. Typed GDScript uses optimized opcodes when types are known at compile time.
var x: int = 5
将脚本附加到节点后,该脚本就是该节点。
- Unity:。
GetComponent<MyScript>() - Godot:脚本 节点类(例如
extends)。extends CharacterBody3D - 专家思维转变:使用 Typed GDScript()获得编译速度提升和 Editor 自动补全。类型已知时,Typed GDScript 可使用优化后的 opcode。
var x: int = 5
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 or for performance. Godot uses .
intEnumStringName- Expert Shift: Use for constant-time (O(1)) pointer comparisons in dictionaries and signal lookups.
&"name"
Unity 为性能使用 或 ,而 Godot 使用 。
intEnumStringName- 专家思维转变:使用 在 Dictionary 和 signal 查找中执行恒定时间(O(1))的指针比较。
&"name"