@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.

View in AI SkillSafe app
10 scan findings
0 downloads
0 stars
0 demos
SKILL.md
namegodot-master
descriptionConsolidated 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 StatsComponent owns health, NOT the CombatSystem)
  • Who is allowed to change it? (Only the owner via a public method like apply_damage())
  • Who needs to know it changed? (Anyone listening to the health_changed signal)

If you can't answer all three for every state variable, your architecture has a coupling problem. This is not OOP encapsulation — this is Godot-specific because the signal system IS the enforcement mechanism, not access modifiers.

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

🧭 Part 2: Architectural Decision Frameworks

The Master Decision Matrix

Scenario Strategy MANDATORY Skill Chain Trade-off
Rapid Prototype Event-Driven Mono READ: FoundationsAutoloads. Do NOT load genre or platform refs. Fast start, spaghetti risk
Complex RPG Component-Driven READ: CompositionStatesRPG Stats. Do NOT load multiplayer or platform refs. Heavy setup, infinite scaling
Massive Open World Resource-Streaming READ: Open WorldSave/Load. Also load Performance. Complex I/O, float precision jitter past 10K units
Server-Auth Multi Deterministic READ: Server ArchMultiplayer. Do NOT load single-player genre refs. High latency, anti-cheat secure
Mobile/Web Port Adaptive-Responsive READ: UI ContainersAdapt Desk→MobilePlatform Mobile. UI complexity, broad reach
Application / Tool App-Composition READ: App CompositionTheming. Do NOT load game-specific refs. Different paradigm than games
Romance / Dating Sim Affection Economy READ: RomanceDialogueUI Rich Text. High UI/Narrative density
Secrets / Easter Eggs Intentional Obfuscation READ: SecretsPersistence. Community engagement, debug risk
Collection Quest Scavenger Logic READ: CollectionsMarker3D Placement. Player retention, exploration drive
Seasonal Event Runtime Injection READ: Easter ThemingMaterial Swapping. Fast branding, no asset pollution
Souls-like Mortality Risk-Reward Revival READ: Revival/Corpse RunPhysics 3D. High tension, player frustration risk
Wave-based Action Combat Pacing Loop READ: WavesCombat. Escalating tension, encounter design
Balance / Difficulty / Economy Pacing Monte Carlo Balance Lab READ: ResourcesEconomyCombat / RPG Stats / Waves (as needed) → Monte Carlo BalancerTestingBuilder. Statistical rigor; abstract sim must calibrate vs headless Godot
Survival Economy Harvesting Loop READ: HarvestingInventory. Resource scarcity, loop persistence
Racing / Speedrun Validation Loop READ: Time TrialsInput BufferGenre Racing. High precision, ghost record drive
Horror / Stealth Tension Management READ: Genre HorrorGenre StealthAudio. Atmosphere, player vulnerability
Card / Board Game Rule Enforcement READ: Genre Card GameTurn System. Deterministic state, UI heavy
Simulation / RTS Batch Processing READ: Genre SimulationGenre RTSPerformance. High unit counts, O(1) logic
HDR / Cinematic Visuals Display Pipeline READ: 3D LightingPlatform DesktopShaders. Enable viewport HDR in Project Settings. Platform-specific tonemapping tuning
Rectangular Area Lights AreaLight3D READ: 3D Lighting3D Materials. Prefer AreaLight3D over emissive+GI hacks. Forward+ renderer required for full quality
Mobile Touch Controls Native Joystick READ: Platform MobileAdapt Desk→Mobile. Use built-in virtual joystick (4.7+). Less plugin dependency
Addon / Asset Discovery Asset Store READ: Project FoundationsExport 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

  1. Organize by Feature (/features/player/, /features/combat/), not by class type. A player/ folder contains the scene, script, resources, and tests for the player.
  2. READ: Signal Architecture — Create GlobalSignalBus autoload with < 15 events.
  3. READ: GDScript Mastery — Enable untyped_declaration warning in Project Settings → GDScript → Debugging.
  4. Apply Project Templates for base .gitignore, export presets, and input map.
  5. Use Builder (builder_create_scene.py, builder_add_node.py, builder_save_scene.py) to generate scene hierarchies programmatically via the Godot CLI.
  6. 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_file or @export_dir to ensure resources remain valid when moved.
  • NEVER initialize children in _init(). The scene tree isn't ready. Use _ready() or @onready.
  • NEVER keep "Default" project settings for Physics Ticks. Set to 60 for consistency, or use Engine.physics_ticks_per_second for adaptive logic.
  • NEVER use print() in _process() for debugging; use the Debugger or push_error() to avoid frame-time spikes.

Do NOT load combat, multiplayer, genre, or platform references during scaffolding.

Workflow 2: Entity Orchestration

Building modular, testable characters.

MANDATORY Chain — READ ALL: CompositionState MachineCharacterBody2D or Physics 3DAnimation Tree Do NOT load UI, Audio, or Save/Load references for entity work.

  • The State Machine queries an InputComponent, never handles input directly. This allows AI/Player swap with zero refactoring.
  • The State Machine ONLY handles transitions. Logic belongs in Components. MoveState tells MoveComponent to act, not the other way around.
  • Every entity MUST pass the F6 test: pressing "Run Current Scene" (F6) must work without crashing. If it crashes, your entity has scene-external dependencies.

[!CAUTION] Workflow 2 NEVER List

  • NEVER call parent.do_thing(). If the parent changes, the entity breaks. Emit a signal request_action instead.
  • NEVER use _process for movement. Use _physics_process to avoid jitter on variable-refresh-rate monitors.
  • NEVER hardcode animation names. Use a StringName constant or a Resource map to enable easy renaming in AnimationPlayer.
  • NEVER use get_node() with absolute paths. Use %UniqueName to survive tree refactoring.

Workflow 3: Data-Driven Systems

Connecting Combat, Inventory, Stats through Resources.

MANDATORY Chain — READ ALL: Resource PatternsRPG StatsCombatInventory

  • Create ONE ItemData.gd extending Resource. Instantiate it as 100 .tres files instead of 100 scripts.
  • The HUD NEVER references the Player directly. It listens for player_health_changed on the Signal Bus.
  • Enable "Local to Scene" on ALL @export Resource variables, or call resource.duplicate() in _ready(). Failure to do this is Bug #1 in Part 8.

[!CAUTION] Workflow 3 NEVER List

  • NEVER pass Node references in a Signal Bus. Objects get freed; RIDs or IDs are safer for long-term tracking.
  • NEVER modify a .tres file at runtime via code (it modifies the disk file). Always .duplicate() before modifying.
  • NEVER use Array for high-frequency search. Use Dictionary with StringName keys for O(1) lookups.
  • NEVER use float for item counts or precise resource tracking; use int and scale for display.

Workflow 4: Persistence Pipeline

MANDATORY: Autoload ArchitectureSave/LoadScene Management

  • Use dictionary-mapped serialization. Old save files MUST not corrupt when new fields are added — use .get("key", default_value).
  • For procedural worlds: save the Seed plus a Delta-List of modifications, not the entire map. A 100MB world becomes a 50KB save.

[!CAUTION] Workflow 4 NEVER List

  • NEVER save whole Object or Node instances. They contain transient pointers. Extract data into a Dictionary or custom Resource.
  • NEVER use JSON for data that needs strict typing (e.g., Vector2). Use var_to_bytes or ConfigFile for structured Godot types.
  • NEVER block the main thread for auto-saves. Use a Thread or WorkerThreadPool to serialize large dictionaries.
  • NEVER save to res:// in an exported project; strictly use user:// for persistent data.

Workflow 5: Performance Optimization

MANDATORY: Debugging/ProfilingPerformance Optimization

Diagnosis-first approach (NEVER optimize blindly):

  1. High Script Time → Profile with built-in Profiler. Check if _process is being called on hundreds of nodes. Move to single-manager pattern or Server APIs (see Part 6).
  2. High Draw Calls → Use MultiMeshInstance for repetitive geometry. Batch materials with ORM textures.
  3. Physics Stutter → Simplify collisions to primitive shapes. Load 2D Physics or 3D Physics. Check if _process is used instead of _physics_process for movement.
  4. VRAM Overuse → Switch textures to VRAM Compression (BPTC/S3TC for desktop, ETC2 for mobile). Never ship raw PNG.
  5. Intermittent Frame Spikes → Usually GC pass, synchronous load(), or NavigationServer recalculation. Use ResourceLoader.load_threaded_request().

[!CAUTION] Workflow 5 NEVER List

  • NEVER use get_nodes_in_group() inside _process. It's an O(n) operation every frame. Cache the array in _ready().
  • NEVER use Area2D signals for "Stay" logic. Use get_overlapping_bodies() periodically or a manager-level PhysicsServer check.
  • NEVER optimize before profiling. A 1ms script is irrelevant if you have 2000 draw calls killing the GPU.
  • NEVER use load() in hot paths; strictly preload or use ResourceLoader for async loading.

Workflow 6: Cross-Platform Adaptation

MANDATORY: Input HandlingAdapt Desktop→MobilePlatform Mobile Also read: Platform Desktop, Platform Web, Platform Console, Platform VR as needed.

  • Use an InputManager autoload that translates all input types into normalized actions. NEVER read Input.is_key_pressed() directly — it blocks controller and touch support.
  • Mobile touch targets: minimum 44px physical size. Use MarginContainer with Safe Area logic for notch/cutout devices.
  • Web exports: Godot's AudioServer requires user interaction before first play (browser policy). Handle this with a "Click to Start" screen.

[!CAUTION] Workflow 6 NEVER List

  • NEVER use OS.get_name() for feature detection. Use OS.has_feature("mobile") or custom feature tags to handle subsets like "SteamDeck."
  • NEVER assume a specific aspect ratio. Always use Expand or Keep Aspect in combinations with Anchor nodes.
  • NEVER use desktop-only shaders (e.g., complex depth sampling) on Mobile/Web without a GLES3/Compatibility secondary path.
  • NEVER ignore physical_keycode for desktop builds; it ensures keyboard layouts (AZERTY/QWERTY) don't break movement.
  • NEVER pass unsanitized strings to JavaScriptBridge.eval() — Prevents script injection in web builds. Use a sanitize_js_string() helper.

Workflow 7: Procedural Generation

MANDATORY: Procedural GenTilemap Mastery or 3D World BuildingNavigation

  • ALWAYS use FastNoiseLite resource with a fixed seed for deterministic generation.
  • Never bake NavMesh on the main thread. Use NavigationServer3D.parse_source_geometry_data() + NavigationServer3D.bake_from_source_geometry_data_async().
  • For infinite worlds: chunk loading MUST happen on a background thread using WorkerThreadPool. Build the scene chunk off-tree, then add_child.call_deferred() on the main thread.

[!CAUTION] Workflow 7 NEVER List

  • NEVER instantiate nodes for "Background" noise. Use MultiMeshInstance or draw loops in _draw for thousands of small details.
  • NEVER regenerate the entire map for one change. Use a "Dirty Chunk" system to only update what exactly changed.
  • NEVER place collisions on the same frame as mesh generation if using concave_polygon_shape. It stalls the physics thread.
  • NEVER perform pathfinding queries every frame for all units. Use a NavigationAgent with target_position updates on a timer.

Workflow 8: Multiplayer Architecture

MANDATORY — READ: Single→MultiplayerNetworkingServer Arch Do NOT load single-player genre blueprints.

  • Client sends Input, Server calculates Outcome. The Client NEVER determines damage, position deltas, or inventory changes.
  • Use Client-Side Prediction with server reconciliation: predict locally, correct from server snapshot. Hides up to ~150ms of latency.
  • MultiplayerSpawner handles replication in Godot 4. Configure it per scene, not globally.

[!CAUTION] Workflow 8 NEVER List

  • NEVER trust rpc_id(1, ...) (Client to Server) without validation. A hacked client can send damage = 999999.
  • NEVER replicate _process transforms directly. Replicate Input vector and simulate movement on both sides.
  • NEVER use TCP for high-frequency packets (movement). Use UDP / ENet and handle dropped packets with interpolation.
  • NEVER synchronize every projectile; use Client-Side Prediction for visuals and only RPC the "Fire" event.
  • ReflectionProbe vs VoxelGI vs SDFGI: Probes are cheap/static, VoxelGI is medium/baked, SDFGI is expensive/dynamic. Choose based on your platform budget (see Part 5).

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

MANDATORY Chain: UI ContainersUI ThemingRich TextTweening

  1. The F6 Principle: Every UI scene must be testable in isolation. Use MOUSE_FILTER_STOP only on the background, PASS on children.
  2. Breathing Room: Use add_theme_constant_override("separation", X) over manual padding.
  3. Adaptive Scaling: Use ui_containers_responsive_layout_builder.gd for breakpoint-aware mobile/desktop switching.
  4. Lifecycle Safety: Never scroll to a new child on the same frame. await get_tree().process_frame before modifying scroll_vertical.
  5. Data Integration: Use Resource-to-UI binding; UI nodes MUST be stateless projection layers.
  6. See it: Close with Workflow 12Agent 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 Container sizing.
  • NEVER deep-nest MarginContainers. It makes the Inspector unusable. Use a single Theme resource for project-wide margins.
  • NEVER connect UI buttons to gameplay logic directly. UI sends "Signal", PlayerController listens. This prevents UI-deletion crashes.
  • NEVER use _process() to move a UI element to a target. Use a Tween to avoid stuttering and frame-rate dependence.
  • NEVER leave mouse_filter as STOP on transparent containers; it "eats" clicks for everything behind it.
  • NEVER use dynamic load() on paths without validating the res:// prefix and safe extension (.tres, .res, .theme) — Prevents arbitrary code/resource execution.
  • NEVER declare UI “done” without an Agent Vision capture of the live layout.

Workflow 10: Cinematic Lighting & VFX (Audit Verified)

MANDATORY Chain: 3D LightingParticles3D MaterialsShaders

  1. The GI Choice: VoxelGI for interiors, SDFGI for open world. Never ship with both overlapping.
  2. Shadow Budget: Max 2 Shadow-casting DirectionalLights. Use 3d_lighting_fake_gi_bounce.gd for mobile fills.
  3. VFX Lifecycle: Use finished signal over Timers. Re-run with restart() to avoid async GPU stalls.
  4. Optimization: Use ORM Texture packing (AO/Rough/Metal) to save GPU cache and texture slots.
  5. Batching: Use Instance Uniforms for material variations across thousands of instances without draw call penalties.
  6. See it: Close with Workflow 12Agent Vision editor/window capture to verify lighting, exposure, and VFX read in pixels.

[!CAUTION] Workflow 10 NEVER List

  • NEVER scale CollisionShape nodes; strictly scale the Shape Resource to avoid physics jitter.
  • NEVER use TRANSPARENCY_ALPHA for cutout meshes (leaves/fences); use ALPHA_SCISSOR to prevent sorting artifacts.
  • NEVER animate CSG nodes during gameplay; forces expensive CPU geometry recalculation.
  • NEVER use real-time Global Illumination (SDFGI/VoxelGI) for a 2D-looking game. Stick to DirectionalLight2D and CanvasModulate.
  • NEVER ignore Camera3D near/far planes; improper settings cause Z-fighting in large worlds.
  • 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.

  1. Step 1: Draft the node hierarchy on paper/markdown before touching disk.
  2. Step 2: Use builder_create_scene.py to define the root node and .tscn path.
  3. Step 3: Use builder_add_node.py for children. Set owner on every node so serialization keeps them.
  4. Step 4: ALWAYS call builder_run_project.py or builder_launch_editor.py to verify the scene loads cleanly.
  5. 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 .tscn loads.
  6. 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.py without designing the hierarchy first — spaghetti scenes follow.
  • NEVER use absolute filesystem paths in scripts or scene props; use res:// only.
  • NEVER add a CollisionShape2D/CollisionShape3D without assigning a Shape resource — the node alone does nothing.
  • NEVER skip verification via builder_run_project.py / builder_launch_editor.py after 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:

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

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:

  1. Setup: pip install -r skills/godot-agent-vision/requirements-vision.txt (host venv). Ensure .gdskills/ is gitignored (agent_vision_ensure_gitignore.py).
  2. Doctor: agent_vision_capture.py doctor — confirm display session / backends.
  3. 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.)
  4. Read the budgeted WebP(s) from .gdskills/vision/ (default short-edge 512). Use --detail only when type/OCR fails at 512.
  5. Score with the Taste Receptor Atlas / vision rubric in the Agent Vision refs — ordered fixes keyed to receptor IDs, not vibes.
  6. 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:

  1. Map: Request the project root; map res:// structure (feature folders, autoloads, dependency hotspots).
  2. Atlas: Load analyst-marking_rubrics_atlas.md — pick the Evolutionary Sector(s) in scope.
  3. Sector only: MANDATORY load matching category rubric file(s) under the Analyst progressive-disclosure tree. Do NOT load every category file.
  4. Engine helpers (only what exists on disk): analyst_scoring_logic.gd, analyst_marking_rubrics_atlas.gd, analyst_visionary_comparison.gd — do not invent phantom score_*.py fleets.
  5. 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/.tres by hand — use ResourceLoader.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:

  1. Survey: Confirm project path + feature-folder integrity.
  2. Encyclopedia: Open auditor-never_list_encyclopedia.md — identify the Architectural Sector.
  3. Surgical load: MANDATORY read only the matching category never-list file(s). Do NOT ingest the entire encyclopedia.
  4. Scanners on disk (call individually — do not invent missing tools):
    • auditor_audit_signals.py — string .connect decay
    • auditor_audit_type_hints.py — untyped Array/Dictionary + string-connect
    • auditor_audit_memory_fragmentation.gd — ObjectDB / orphan snapshots
    • auditor_purge_report_generator.gd — purge / unused-resource rollup
  5. 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_*.py scanners that are not in scripts/.
  • 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.

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

📊 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 RenderingServer with RIDs instead of Sprite2D/MeshInstance3D nodes.
  • Bullet-hell / particle systems with script interaction: Use PhysicsServer2D body creation instead of Area2D nodes.
  • Mass physics simulation: Use PhysicsServer3D directly for ragdoll fields, debris, or fluid-like simulations.

📊 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 Resource from multiple threads simultaneously — use one loading thread.

🧩 Part 7: Expert Code Patterns

Expert implementations of common architectural and gameplay systems.


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

  1. @export Resources are shared by default: Multiple scene instances ALL share the same Resource. Use resource.duplicate() in _ready() or enable "Local to Scene" checkbox. This is the #1 most reported Godot 4 bug by newcomers.
  2. Signal syntax silently fails: connect("signal_name", target, "method") (Godot 3 syntax) compiles but does nothing in Godot 4. Must use signal_name.connect(callable).
  3. Tween is no longer a Node: Created via create_tween(), bound to the creating node's lifetime. If that node is freed, the Tween dies. Use get_tree().create_tween() for persistent tweens.
  4. PhysicsBody layers vs masks: collision_layer = "what I am". collision_mask = "what I scan for". Setting both to the same value causes self-collision or missed detections.
  5. StringName vs String in hot paths: StringName (&"key") uses pointer comparison (O(1)). String uses character comparison (O(n)). Always use StringName for dictionary keys in _process.
  6. @onready timing: Runs AFTER _init() but DURING _ready(). If you need constructor-time setup, use _init(). If you need tree access, use @onready or _ready(). Mixing them causes nulls.

Embed badges

Add these to your README to show the skill's verification status.

SkillSafe verified badge
Verified badge
[![SkillSafe verified badge](https://api.skillsafe.ai/v1/badge/@thedivergentai/godot-master/verified)](https://skillsafe.ai/skill/@thedivergentai/godot-master/)
Installs badge
Installs badge
[![Installs badge](https://api.skillsafe.ai/v1/badge/@thedivergentai/godot-master/installs)](https://skillsafe.ai/skill/@thedivergentai/godot-master/)
Scan badge
Scan badge
[![Scan badge](https://api.skillsafe.ai/v1/badge/@thedivergentai/godot-master/scan)](https://skillsafe.ai/skill/@thedivergentai/godot-master/)
Eval pass rate badge
Eval pass rate
[![Eval pass rate badge](https://api.skillsafe.ai/v1/badge/@thedivergentai/godot-master/eval)](https://skillsafe.ai/skill/@thedivergentai/godot-master/)