From godot-dev
Godot 4.x GDScript architecture patterns and project conventions. Guides pattern selection, enforces naming/typing conventions, and provides on-demand implementation references.
How this skill is triggered — by the user, by Claude, or both
Slash command
/godot-dev:godot-gdscript-patternssonnetThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
- Files/variables/functions: `snake_case`
snake_casePascalCaseSCREAMING_SNAKE_CASEsnake_case past tense (health_changed, died)@export for inspector, @onready for node refs## docstrings (double hash) for public API, not # comments.tres) for data, scripts for logic — never hardcode tunable valuesget_node() chains between systemsWhen building a new system, choose pattern based on the problem:
| Problem | Pattern | When NOT to use |
|---|---|---|
| Entity with multiple behavior modes | State Machine | <3 states (just use if/match) |
| Shared behavior across entity types | Component System | Behavior only used by 1 entity type |
| Game-wide event communication | Signal Bus (EventBus autoload) | Direct parent-child communication |
| Data variation (weapons, enemies, items) | Resource (.tres files) | Runtime-only calculated values |
| Frequently spawned/destroyed objects | Object Pool | <20 objects or infrequent spawning |
| Async scene transitions | Scene Manager | Simple get_tree().change_scene_to_file() |
| Persistent game state | Save Manager (JSON) | .tres for saves (fragile on refactor) |
If the pattern needs more detail, read the reference file:
references/state-machine.md — Full StateMachine + State base class implementationreferences/components.md — HealthComponent, Hitbox/Hurtbox, KnockbackComponentreferences/save-system.md — Multi-slot JSON save with previewreferences/object-pool.md — Generic ObjectPool with signal-based returnprocess_mode on inactive states — don't just skip update callsmsg: Dictionary to enter() for state-specific initialization datatransition_to() should disable old state's processing BEFORE enabling new stateCONNECT_ONE_SHOT for cleanup connections that should fire onceis_connected() before connecting in code that may run multiple timesduplicate() resources at runtime if multiple instances share the same .tresduplicate(), not beforeclass_name on Resource subclasses for typed exportsawait BEFORE swapping scenes, not afterawait inside pool return logic (blocks the pool).tres for save files (class rename breaks .tres loads)tween.chain() is cleaner than sequential await_ready(), never $Path in _process()distance_squared_to() instead of distance_to() in hot paths (avoids sqrt)set_physics_process(false) on off-screen or idle entitiesqueue_free() + instantiate() every framearray.clear() instead of var array = []Array[Node2D]) — faster iteration than untypednpx claudepluginhub haingt-dev/agent --plugin godot-devCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.