@thedivergentai/godot-master
Consolidated expert library for professional Godot 4.x game and application development. Orchestrates 94 specialized blueprints through architectural workflows, anti-pattern catalogs, performance budgets, and Server API patterns. Use when: (1) starting a new Godot project, (2) designing game or app architecture, (3) building entity/component systems, (4) debugging performance or physics issues, (5) choosing between 2D/3D approaches, (6) implementing multiplayer, (7) optimizing draw calls or script time, (8) porting between platforms. Primary entry point for ALL Godot development tasks.
| name | godot-master |
| description | Consolidated expert library for professional Godot 4.7+ game and application development. Orchestrates 92 Domain Skills through architectural workflows, anti-pattern catalogs, performance budgets, and Server API patterns. Use when: (1) starting a new Godot project, (2) designing game or app architecture, (3) building entity/component systems, (4) debugging performance or physics issues, (5) choosing between 2D/3D approaches, (6) implementing multiplayer, (7) optimizing draw calls or script time, (8) porting between platforms, (9) migrating from 4.6 to 4.7, (10) visually verifying UI/editor/game appearance via Agent Vision, (11) scoring/certifying architecture with Analyst (Anara), (12) enforcing never-lists with Auditor (Aurelius), (13) programmatic CLI scene building with Builder. Primary entry point for ALL Godot development tasks. Keywords: Godot 4.7, AreaLight3D, HDR, Asset Store, godot-master, agent vision, visual QA, Agent Eyes, analyst, Anara, auditor, Aurelius, builder. |
Godot Master: Lead Architect Knowledge Hub
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.
Library target — 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.
🧠 Part 1: Expert Thinking Frameworks
"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
StatsComponentowns health, NOT theCombatSystem) - 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_changedsignal)
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.
The Godot "Layer Cake"
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.
The Signal Bus Tiered Architecture
- 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.,
CombatBusonly for combat nodes). This is the compromise that scales. - Direct Signals: Parent-child communication WITHIN a single scene. Never across scene boundaries.
🔗 The "Smart Interconnect" Mandate
Expert systems are defined not by their isolation, but by their Payload Synthesis.
- Physics → Performance:
PhysicsServer2DandRenderingServerbypassSceneTreenode overhead. Use for 1,000+ bullets or particles to achieve O(1) processing. - Animation → Physics:
AnimationTree.get_root_motion_position()converts animation displacement into physicsvelocity, preventing "foot sliding" in complex movement. - Data → Reactivity: Serialized
Resourceobjects (likeStats) emit signals when modified, allowing UI to update automatically without tight coupling. - Asset → Spawning: An O(1) Dictionary-based cache (preloaded during
ResourceLoaderasync phases) prevents I/O hitches when spawning items or enemies. - Eyes → Verification: After UI, lighting, or scene-building work, agents must see the current representation — route to Agent Vision (capture → budgeted WebP → scored taste), not verbal guesswork.
- Score → Certify: Before calling architecture “production-ready,” route to Analyst (Anara) — rubric sectors + helper scripts, not vibes.
- Slop → Decree: Before merge/ship, route to Auditor (Aurelius) — never-list encyclopedia + deterministic scanners.
- 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
PackedByteArrayfor synchronization instead of JSON/Strings to keep packets under 100 bytes. - Genre Synthesis:
Shooter: strictly useintersect_ray()(direct space state) overRayCast3Dnodes for 100x performance.RPG: Damage followsbase * pow(scaling, level)to sustain end-game progression.RTS: Moves groups based on their Center of Mass withRelative Offsetto preserve formation integrity.Metroidvania: UsesResourceLoader.load_threaded_request()for seamless room swaps.Platformer: MandatoryJump Buffering(~0.15s) andCoyote Timefor professional feel.Simulation:Tick Managerbatch processing; avoid per-entity_processto sustain thousands of units.Romance:Multi-Axial Affection(Attraction, Trust, Comfort) to map complex narrative branching.Architecture:Signal Architecturestrictly followsSignal Up, Call Downto eliminate circular scene coupling.
🧭 Part 2: Architectural Decision Frameworks
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 |
| CLI Scene / Headless Build | Builder Pipeline | READ: Builder. Programmatic .tscn / glTF→collision / CI export via prefixed builder_*.py. Do NOT load genre refs. |
Structure only — pair with Agent Vision for pixels |
| Architecture Score / Certificate | Analyst (Anara) | READ: Analyst → marking rubrics atlas → active sector category only. | Certifies scale/cohesion — not “it runs” |
| Never-List / Slop Audit | Auditor (Aurelius) | READ: Auditor → never-list encyclopedia → active sector + scanners on disk. | Surgical load — do not ingest entire encyclopedia |
| 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 |
The "When NOT to Use a Node" Decision
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 |
|---|---|---|---|
Object |
Custom data structures, manual memory management | Lightest. Must call .free() manually. |
Custom spatial hash maps, ECS-like data stores |
RefCounted |
Transient data packets, logic objects that auto-delete | Auto-deleted when no refs remain. | DamageRequest, PathQuery, AbilityEffect — logic packets that don't need the scene tree |
Resource |
Serializable data with Inspector support | Slightly 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.
🔧 Part 3: Core Workflows
Workflow 1: Professional Scaffolding
From empty project to production-ready container.
MANDATORY — READ ENTIRE FILE: Foundations
- Organize by Feature (
/features/player/,/features/combat/), not by class type. Aplayer/folder contains the scene, script, resources, and tests for the player. - READ: Signal Architecture — Create
GlobalSignalBusautoload with < 15 events. - READ: GDScript Mastery — Enable
untyped_declarationwarning in Project Settings → GDScript → Debugging. - Apply Project Templates for base
.gitignore, export presets, and input map. - Use Builder (
builder_create_scene.py,builder_add_node.py,builder_save_scene.py) to generate scene hierarchies programmatically via the Godot CLI. - After the container exists: optional early Workflow 13 (Analyst) on foundations cohesion; before first ship, Workflow 14 (Auditor) on signal/typing/export never-lists.
[!CAUTION] Workflow 1 NEVER List
- NEVER use
res://paths in logic scripts. Use@export_fileor@export_dirto 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 useEngine.physics_ticks_per_secondfor adaptive logic.- NEVER use
print()in_process()for debugging; use theDebuggerorpush_error()to avoid frame-time spikes.
Do NOT load combat, multiplayer, genre, or platform references during scaffolding.
Workflow 2: Entity Orchestration
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.
MoveStatetellsMoveComponentto 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 signalrequest_actioninstead.- NEVER use
_processfor movement. Use_physics_processto avoid jitter on variable-refresh-rate monitors.- NEVER hardcode animation names. Use a
StringNameconstant or aResourcemap to enable easy renaming inAnimationPlayer.- NEVER use
get_node()with absolute paths. Use%UniqueNameto survive tree refactoring.
Workflow 3: Data-Driven Systems
Connecting Combat, Inventory, Stats through Resources.
MANDATORY Chain — READ ALL: Resource Patterns → RPG Stats → Combat → Inventory
- Create ONE
ItemData.gdextendingResource. Instantiate it as 100.tresfiles instead of 100 scripts. - The HUD NEVER references the Player directly. It listens for
player_health_changedon the Signal Bus. - Enable "Local to Scene" on ALL
@export Resourcevariables, or callresource.duplicate()in_ready(). Failure to do this is Bug #1 in Part 8.
[!CAUTION] Workflow 3 NEVER List
- NEVER pass
Nodereferences in a Signal Bus. Objects get freed; RIDs or IDs are safer for long-term tracking.- NEVER modify a
.tresfile at runtime via code (it modifies the disk file). Always.duplicate()before modifying.- NEVER use
Arrayfor high-frequency search. UseDictionarywithStringNamekeys for O(1) lookups.- NEVER use
floatfor item counts or precise resource tracking; useintand scale for display.
Workflow 4: Persistence Pipeline
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
ObjectorNodeinstances. They contain transient pointers. Extract data into aDictionaryor customResource.- NEVER use
JSONfor data that needs strict typing (e.g.,Vector2). Usevar_to_bytesorConfigFilefor structured Godot types.- NEVER block the main thread for auto-saves. Use a
ThreadorWorkerThreadPoolto serialize large dictionaries.- NEVER save to
res://in an exported project; strictly useuser://for persistent data.
Workflow 5: Performance Optimization
MANDATORY: Debugging/Profiling → Performance Optimization
Diagnosis-first approach (NEVER optimize blindly):
- High Script Time → Profile with built-in Profiler. Check if
_processis being called on hundreds of nodes. Move to single-manager pattern or Server APIs (see Part 6). - High Draw Calls → Use
MultiMeshInstancefor repetitive geometry. Batch materials with ORM textures. - Physics Stutter → Simplify collisions to primitive shapes. Load 2D Physics or 3D Physics. Check if
_processis used instead of_physics_processfor movement. - 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
load(), or NavigationServer recalculation. UseResourceLoader.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
Area2Dsignals for "Stay" logic. Useget_overlapping_bodies()periodically or a manager-levelPhysicsServercheck.- NEVER optimize before profiling. A 1ms script is irrelevant if you have 2000 draw calls killing the GPU.
- NEVER use
load()in hot paths; strictlypreloador useResourceLoaderfor async loading.
Workflow 6: Cross-Platform Adaptation
MANDATORY: Input Handling → Adapt Desktop→Mobile → Platform Mobile Also read: Platform Desktop, Platform Web, Platform Console, Platform VR as needed.
- Use an
InputManagerautoload that translates all input types into normalized actions. NEVER readInput.is_key_pressed()directly — it blocks controller and touch support. - Mobile touch targets: minimum 44px physical size. Use
MarginContainerwith Safe Area logic for notch/cutout devices. - Web exports: Godot's
AudioServerrequires 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. UseOS.has_feature("mobile")or custom feature tags to handle subsets like "SteamDeck."- NEVER assume a specific aspect ratio. Always use
ExpandorKeep Aspectin combinations withAnchornodes.- NEVER use desktop-only shaders (e.g., complex depth sampling) on Mobile/Web without a GLES3/Compatibility secondary path.
- NEVER ignore
physical_keycodefor 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 asanitize_js_string()helper.
Workflow 7: Procedural Generation
MANDATORY: Procedural Gen → Tilemap Mastery or 3D World Building → Navigation
- ALWAYS use
FastNoiseLiteresource with a fixedseedfor 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, thenadd_child.call_deferred()on the main thread.
[!CAUTION] Workflow 7 NEVER List
- NEVER instantiate nodes for "Background" noise. Use
MultiMeshInstanceor draw loops in_drawfor 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
NavigationAgentwithtarget_positionupdates on a timer.
Workflow 8: Multiplayer Architecture
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.
MultiplayerSpawnerhandles 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 senddamage = 999999.- NEVER replicate
_processtransforms directly. ReplicateInputvector and simulate movement on both sides.- NEVER use
TCPfor high-frequency packets (movement). UseUDP/ENetand handle dropped packets with interpolation.- NEVER synchronize every projectile; use Client-Side Prediction for visuals and only RPC the "Fire" event.
ReflectionProbevsVoxelGIvsSDFGI: Probes are cheap/static, VoxelGI is medium/baked, SDFGI is expensive/dynamic. Choose based on your platform budget (see Part 5).
Workflow 9: Responsive UI & Expert Theming (Audit Verified)
MANDATORY Chain: UI Containers → UI Theming → Rich Text → Tweening
- The F6 Principle: Every UI scene must be testable in isolation. Use
MOUSE_FILTER_STOPonly on the background,PASSon children. - Breathing Room: Use
add_theme_constant_override("separation", X)over manual padding. - Adaptive Scaling: Use
ui_containers_responsive_layout_builder.gdfor breakpoint-aware mobile/desktop switching. - Lifecycle Safety: Never scroll to a new child on the same frame.
await get_tree().process_framebefore modifyingscroll_vertical. - Data Integration: Use
Resource-to-UIbinding; UI nodes MUST be stateless projection layers. - See it: Close with Workflow 12 — Agent Vision window/asset capture → scored layout/type review. Agents cannot QA UI from text alone.
[!CAUTION] Workflow 9 NEVER List
- NEVER use absolute pixel offsets. UI becomes unreadable on 4K or tiny mobile screens. Use
Containersizing.- NEVER deep-nest
MarginContainers. It makes the Inspector unusable. Use a singleThemeresource for project-wide margins.- NEVER connect UI buttons to gameplay logic directly. UI sends "Signal",
PlayerControllerlistens. This prevents UI-deletion crashes.- NEVER use
_process()to move a UI element to a target. Use aTweento avoid stuttering and frame-rate dependence.- NEVER leave
mouse_filterasSTOPon transparent containers; it "eats" clicks for everything behind it.- NEVER use dynamic
load()on paths without validating theres://prefix and safe extension (.tres,.res,.theme) — Prevents arbitrary code/resource execution.- NEVER declare UI “done” without an Agent Vision capture of the live layout.
Workflow 10: Cinematic Lighting & VFX (Audit Verified)
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
3d_lighting_fake_gi_bounce.gdfor mobile fills. - VFX Lifecycle: Use
finishedsignal over Timers. Re-run withrestart()to avoid async GPU stalls. - Optimization: Use
ORM Texturepacking (AO/Rough/Metal) to save GPU cache and texture slots. - Batching: Use
Instance Uniformsfor material variations across thousands of instances without draw call penalties. - See it: Close with Workflow 12 — Agent Vision editor/window capture to verify lighting, exposure, and VFX read in pixels.
[!CAUTION] Workflow 10 NEVER List
- NEVER scale
CollisionShapenodes; strictly scale the Shape Resource to avoid physics jitter.- NEVER use
TRANSPARENCY_ALPHAfor cutout meshes (leaves/fences); useALPHA_SCISSORto 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
DirectionalLight2DandCanvasModulate.- NEVER ignore
Camera3Dnear/far planes; improper settings cause Z-fighting in large worlds.- NEVER trust lighting “looks fine” from code alone — capture the viewport with Agent Vision.
Workflow 11: Programmatic Scene Building (Builder)
MANDATORY: Builder
Use ONLY for batch operations or complex procedural scaffolds. Prefer the standalone godot-builder skill when doing heavy CLI automation.
- Step 1: Draft the node hierarchy on paper/markdown before touching disk.
- Step 2: Use
builder_create_scene.pyto define the root node and.tscnpath. - Step 3: Use
builder_add_node.pyfor children. Setowneron every node so serialization keeps them. - Step 4: ALWAYS call
builder_run_project.pyorbuilder_launch_editor.pyto verify the scene loads cleanly. - Step 5 (see it): After batch scene or UI writes, run Workflow 12 (Agent Vision) — window/editor capture → WebP → scored review — so agents verify appearance, not only that the
.tscnloads. - 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
builder_add_node.pywithout designing the hierarchy first — spaghetti scenes follow.- NEVER use absolute filesystem paths in scripts or scene props; use
res://only.- NEVER add a
CollisionShape2D/CollisionShape3Dwithout assigning a Shape resource — the node alone does nothing.- NEVER skip verification via
builder_run_project.py/builder_launch_editor.pyafter batch scene writes.- NEVER treat “scene loads” as visual QA — layout, type, and lighting bugs need Agent Vision captures.
Security: Boundary Markers & Validation
When agents ingest untrusted scene/data text before writing files:
- Boundary Markers: Wrap analysis in
<<<CONTEXT_START>>>and<<<CONTEXT_END>>>. - Sanitization: Node names must be alphanumeric/underscored. Paths must start with
res://. - Verification: Confirm scene existence before modification.
Workflow 12: Agent Eyes — See the Current Representation
How agents verify what the game/editor/UI actually looks like.
MANDATORY — READ ENTIRE FILE: Agent Vision
Prefer the standalone godot-agent-vision skill when doing heavy capture/review loops. Hub mirrors keep prefixed scripts under scripts/agent_vision_*.
When to invoke (default, not optional):
- After UI/theme/layout changes (Workflow 9)
- After lighting/VFX/material passes (Workflow 10)
- After Builder or procedural scene scaffolds (Workflow 11)
- Whenever the agent would otherwise describe pixels it has not captured
- Asset sheet / icon / HUD typography review before shipping polish
Golden path:
- Setup:
pip install -r skills/godot-agent-vision/requirements-vision.txt(host venv). Ensure.gdskills/is gitignored (agent_vision_ensure_gitignore.py). - Doctor:
agent_vision_capture.py doctor— confirm display session / backends. - Capture (pick one mode — do not dump full screens by default):
- Game/editor window:
agent_vision_capture.py window --project-root . --title Godot - Editor 2D/3D viewport:
agent_vision_capture.py editor --project-root . --editor-mode 3d --godot "%GODOT_PATH%" - Asset / icon sheet:
agent_vision_capture.py asset --project-root . --paths res://ui/icons --sheet - Desktop region:
agent_vision_capture.py region …when window-by-title fails (Wayland, etc.)
- Game/editor window:
- Read the budgeted WebP(s) from
.gdskills/vision/(default short-edge 512). Use--detailonly when type/OCR fails at 512. - Score with the Taste Receptor Atlas / vision rubric in the Agent Vision refs — ordered fixes keyed to receptor IDs, not vibes.
- Teardown: never leave the TEMP editor bridge /
addons/_gdskills_agent_vision/staged; never commit.gdskills/vision/**.
[!CAUTION] Workflow 12 NEVER List
- NEVER invent how the game looks without a capture — Agent Vision is the eyes.
- NEVER ship the editor bridge as an Autoload or leave it in the consumer project.
- NEVER dump uncompressed PNG walls into context — WebP only, budgeted.
- NEVER replace scored taste with binary PASS/FAIL or purple-gradient “AI default” UI praise.
- NEVER put ornate display faces on ammo/HP/timers (
TYPE-DISPLAY-HUD-SPLIT).
Workflow 13: Architecture Scoring — Analyst (Anara)
Certify whether the project can survive tomorrow — not whether it merely runs.
MANDATORY — READ ENTIRE FILE: Analyst
Prefer the standalone godot-analyst skill for full certification loops. Hub mirrors: scripts/analyst_*, nested references/analyst-*.md.
When to invoke:
- Before calling a milestone “architecture complete”
- After large refactors (folder-by-feature, autoload sprawl, Resource graphs)
- When the user asks for modernity / scalability / Visionary Certificate scoring
- After Workflow 1 scaffolding or Workflow 2–4 systems land — score cohesion before more features
Golden path:
- Map: Request the project root; map
res://structure (feature folders, autoloads, dependency hotspots). - Atlas: Load analyst-marking_rubrics_atlas.md — pick the Evolutionary Sector(s) in scope.
- Sector only: MANDATORY load matching category rubric file(s) under the Analyst progressive-disclosure tree. Do NOT load every category file.
- Engine helpers (only what exists on disk):
analyst_scoring_logic.gd,analyst_marking_rubrics_atlas.gd,analyst_visionary_comparison.gd— do not invent phantomscore_*.pyfleets. - Synthesize: Weighted scores → Visionary Certificate narrative + transcendence blueprint (gaps ordered by impact).
[!CAUTION] Workflow 13 NEVER List
- NEVER certify without the active sector rubric — guessing weights is not Visionary.
- NEVER parse
.tscn/.tresby hand — useResourceLoader.get_dependencies/PackedScene.get_state.- NEVER treat “it runs” or green play as a pass — score scale, typing, decoupling, cohesion.
- NEVER load the entire Analyst categories tree into context.
Workflow 14: Never-List Enforcement — Auditor (Aurelius)
Find the invisible slop that invites bugs — then decree remediation.
MANDATORY — READ ENTIRE FILE: Auditor
Prefer the standalone godot-auditor skill for deep audits. Hub mirrors: scripts/auditor_*, nested references/auditor-*.md.
When to invoke:
- Pre-merge / pre-release integrity pass
- After signal, typing, export, or memory regressions
- When Analyst scores flag decay — Auditor proves it with scanners + encyclopedia
- Pair with Workflow 5 (performance) when ObjectDB / orphan / batching slop is suspected
Golden path:
- Survey: Confirm project path + feature-folder integrity.
- Encyclopedia: Open auditor-never_list_encyclopedia.md — identify the Architectural Sector.
- Surgical load: MANDATORY read only the matching category never-list file(s). Do NOT ingest the entire encyclopedia.
- Scanners on disk (call individually — do not invent missing tools):
auditor_audit_signals.py— string.connectdecayauditor_audit_type_hints.py— untyped Array/Dictionary + string-connectauditor_audit_memory_fragmentation.gd— ObjectDB / orphan snapshotsauditor_purge_report_generator.gd— purge / unused-resource rollup
- Decrees: Findings with the why behind each never-list hit; ordered remediation. For sectors without a scanner, cite engine APIs from the loaded category — do not claim a phantom script ran.
[!CAUTION] Workflow 14 NEVER List
- NEVER load every never-list category at once — progressive disclosure only.
- NEVER invent
audit_*.pyscanners that are not inscripts/.- NEVER soft-pedal export case-sensitivity, signal decay, or untyped hot-path collections.
- NEVER skip deterministic proof when a scanner exists for the request.
Persona triad (ship loop): Builder builds structure → Agent Vision sees pixels → Analyst scores architecture → Auditor enforces never-lists.
🚫 Part 4: The Expert NEVER List
Each rule includes the non-obvious reason — the thing only shipping experience teaches.
- 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. - NEVER use
load()inside a loop or_process— Synchronous disk read blocks the ENTIRE main thread. Usepreload()at script top for small assets,ResourceLoader.load_threaded_request()for large ones. - 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 tonullbefore freeing. - NEVER put gameplay logic in
_draw()—_draw()is called on the rendering thread. Mutating game state causes race conditions with_physics_process. - NEVER use
Area2Dfor 1000+ overlapping objects — Each overlap check has O(n²) broadphase cost. UseShapeCast2D,PhysicsDirectSpaceState2D.intersect_shape(), or Server APIs for bullet-hell patterns. - NEVER mutate external state from a component — If
HealthComponentcalls$HUD.update_bar(), deleting the HUD crashes the game. Components emit signals; listeners decide how to respond. - NEVER use
awaitin_physics_process—awaityields execution, meaning the physics step skips frames. Move async operations to a separate method triggered by a signal. - NEVER use
Stringkeys in hot-path dictionary lookups — String hashing is O(n). UseStringName(&"key") for O(1) pointer comparisons, or integer enums. - NEVER store
Callablereferences to freed objects — Crashes silently or throws errors. Disconnect signals in_exit_tree()or useCONNECT_ONE_SHOT. - NEVER use
_processfor 1000+ entities — Each_processcall has per-node SceneTree overhead. Use a singleManager._processthat iterates an array of data structs (Data-Oriented pattern), or use Server APIs directly. - NEVER use
Tweenon a node that may be freed — If a node isqueue_free()'d while a Tween runs, it errors. Kill tweens in_exit_tree()or bind to SceneTree:get_tree().create_tween(). - NEVER request data FROM
RenderingServerorPhysicsServerin_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. - 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. - 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
super()chains is a nightmare. Use composition (Nodechildren) to add behaviors instead. - NEVER use
_processfor hit detection or movement in physics-heavy genres (FPS/ARPG); strictly use_physics_processto ensure frame-independent collision detection. - 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
StringName(&"active") to avoid O(n) hashing. - NEVER manually handle RVO avoidance every frame in unit-heavy games (RTS/MOBA); offload to
NavigationAgentinternal threading. - NEVER block the main thread for procedural generation or heavy I/O; strictly offload to
WorkerThreadPool. - NEVER ignore
Local-to-Sceneon Resources used in unique instances (e.g. enemy stats); failure causes shared-memory bugs across all instances. - NEVER use
floatfor currency; strictly use Integer Cents to avoid precision drift in complex economies. - NEVER set
target_positionbeforephysics_frame; navigation maps are not ready during_ready(). - NEVER use
TRANSPARENCY_HASHorALPHAfor large cutout surfaces (foliage); useALPHA_SCISSORfor performance and sorting. - NEVER scale
CollisionShapenodes (Node2D/3D scale) — Use shape handles or resize the resource to avoid unpredictable physics normals and jitter. - 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. - 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
InputEventScreenTouchandInputEventScreenDragfor reliable multi-touch support. - 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
StringName(&"active") to avoid O(n) hashing overhead. - NEVER trust the client for game state (Health, Inventory) — Clients suggest actions; Server validates and broadcasts to prevent cheating.
- NEVER use
ReliableRPCs for movement updates — UseUnreliableOrderedto prevent Head-of-Line blocking in high-latency scenarios.
📊 Part 5: Performance Budgets (Concrete Numbers)
| Metric | Mobile Target | Desktop Target | Expert Note |
|---|---|---|---|
| Draw Calls | < 100 (2D), < 200 (3D) | < 500 | MultiMeshInstance for foliage/debris |
| 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 PhysicsServer direct API for mass sim |
| Particles | < 2000 total | < 10000 total | GPU particles, set visibility_aabb manually |
| 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 | ResourceLoader.load_threaded_request() |
⚙️ Part 6: Server APIs — The Expert Performance Escape Hatch
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.
When to Drop to Server APIs
- 10K+ rendered instances (sprites, meshes): Use
RenderingServerwith RIDs instead ofSprite2D/MeshInstance3Dnodes. - Bullet-hell / particle systems with script interaction: Use
PhysicsServer2Dbody creation instead ofArea2Dnodes. - Mass physics simulation: Use
PhysicsServer3Ddirectly for ragdoll fields, debris, or fluid-like simulations.
📊 Performance Comparison: SceneTree vs. Server APIs
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 _process for every instance. Servers batch operations in C++. |
| 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.
The RID Pattern (Expert)
Server APIs communicate through RID (Resource ID) — opaque handles to server-side objects. Critical rules:
# Create server-side canvas item (NO node overhead)
var ci_rid := RenderingServer.canvas_item_create()
RenderingServer.canvas_item_set_parent(ci_rid, get_canvas_item())
# CRITICAL: Keep resource references alive. RIDs don't count as references.
# If the Texture resource is GC'd, the RID becomes invalid silently.
var texture: Texture2D = preload("res://sprite.png")
RenderingServer.canvas_item_add_texture_rect(ci_rid, Rect2(-texture.get_size() / 2, texture.get_size()), texture)
Threading with Servers
- 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
Resourcefrom multiple threads simultaneously — use one loading thread.
🧩 Part 7: Expert Code Patterns
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.
🔥 Part 8: Godot 4.x Gotchas (Veteran-Only)
@exportResources are shared by default: Multiple scene instances ALL share the sameResource. Useresource.duplicate()in_ready()or enable "Local to Scene" checkbox. This is the #1 most reported Godot 4 bug by newcomers.- Signal syntax silently fails:
connect("signal_name", target, "method")(Godot 3 syntax) compiles but does nothing in Godot 4. Must usesignal_name.connect(callable). Tweenis no longer a Node: Created viacreate_tween(), bound to the creating node's lifetime. If that node is freed, the Tween dies. Useget_tree().create_tween()for persistent tweens.PhysicsBodylayers 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.StringNamevsStringin hot paths:StringName(&"key") uses pointer comparison (O(1)).Stringuses character comparison (O(n)). Always useStringNamefor dictionary keys in_process.@onreadytiming: Runs AFTER_init()but DURING_ready(). If you need constructor-time setup, use_init(). If you need tree access, use@onreadyor_ready(). Mixing them causes nulls.
Loading...
Select a file to preview
Analyzing security...
Checking scan reports and verification data.
Bill of Materials
Everything this skill can do — files, network, commands, and more.