Claude
Skills
Sign in
โ† Back

godot-project-foundations

Included with Lifetime
$97 forever

Expert blueprint for Godot 4 project organization (feature-based folders, naming conventions, version control). Enforces snake_case files, PascalCase nodes, %SceneUniqueNames, and .gitignore best practices. Use when starting new projects or refactoring structure. Keywords project organization, naming conventions, snake_case, PascalCase, feature-based, .gitignore, .gdignore.

Generalscripts

What this skill does


# Project Foundations

Feature-based organization, consistent naming, and version control hygiene define professional Godot projects.

## Available Scripts

### ๐Ÿ›๏ธ Core Scaffolding (Stateful / Persistent)
Stateful managers and controllers that persist in the SceneTree or handle global lifecycle events.

- **[project_bootstrapper.gd](scripts/project_bootstrapper.gd)**: Auto-generates feature folders and .gitignore.
- **[runtime_configurator.gd](scripts/runtime_configurator.gd)**: Applies high-performance profiles and saves `override.cfg`.
- **[managed_autoload.gd](scripts/managed_autoload.gd)**: Advanced Singleton pattern with `RefCounted` delegation.
- **[global_event_bus.gd](scripts/global_event_bus.gd)**: Strongly-typed global Signal Bus for system decoupling.
- **[node_pooling_system.gd](scripts/node_pooling_system.gd)**: Thread-safe Object Pool for high-frequency scene instantiation.
- **[async_resource_loader.gd](scripts/async_resource_loader.gd)**: Threaded non-blocking scene loading with progress status.

### ๐Ÿ› ๏ธ Runtime Utilities (Stateless / Lightweight)
Stateless helper scripts, static libraries, and custom data containers (Resource/RefCounted).

- **[base_data_resource.gd](scripts/base_data_resource.gd)**: Reactive Resource foundation using `emit_changed()`.
- **[advanced_telemetry_logger.gd](scripts/advanced_telemetry_logger.gd)**: Custom OS-level `Logger` for crash reporting.
- **[threaded_task_worker.gd](scripts/threaded_task_worker.gd)**: Robust `WorkerThreadPool` implementation.
- **[action_buffer_input.gd](scripts/action_buffer_input.gd)**: Foundational `_unhandled_input` buffer.
- **[build_metadata_provider.gd](scripts/build_metadata_provider.gd)**: Native extraction of version and build metadata.

> **Do NOT Load** dependency_auditor.gd unless troubleshooting loading errors.


## NEVER Do (Expert Anti-Patterns)

### Global Architecture
- **NEVER group by file type** โ€”  `/scripts`, `/sprites` folders. Nightmare maintainability. Use feature-based: `/player`, `/ui`.
- **NEVER mix snake_case and PascalCase in files** โ€” Standard: snake_case for files, PascalCase for nodes.
- **NEVER use hardcoded get_node() paths** โ€” Brittle on reparenting. Use `%SceneUniqueNames` for stable references.
- **NEVER use monolithic Autoloads** โ€” Avoid managers that hold visual node references; keep singletons focused on pure data or RefCounted delegation.

### Resource Management
- **NEVER forget .gitignore**  โ€” Committing `.godot/` folder = 100MB+ bloat + conflicts.
- **NEVER skip .gdignore for raw assets** โ€” Design source files (`.psd`, `.blend`) in root will be imported unless ignored.
- **NEVER modify globally shared Resources directly** โ€” Strictly call `duplicate(true)` for unique instances with independent state.

### Performance & Threading
- **NEVER block the main thread with `load()`** โ€” Strictly use `ResourceLoader.load_threaded_request()` for async scene transitions.
- **NEVER modify the SceneTree from a background thread** โ€” Strictly use `call_deferred()` for thread-to-main-thread synchronization.
- **NEVER skip Mutex locking during pooled access** โ€” Strictly ensure thread-safety when using a shared `WorkerThreadPool` or Object Pool.
- **NEVER use `_process()` for precise input** โ€” Tied to visual framerate. Strictly use `_unhandled_input()` to capture exact, frame-independent events.

---

### 1. Naming Conventions
- **Files & Folders**: Always use `snake_case`. (e.g., `player_controller.gd`, `main_menu.tscn`).
    - *Exception*: C# scripts use `PascalCase` for class-match.
- **Node Names**: Always use `PascalCase` (e.g., `PlayerSprite`, `CollisionShape2D`).
- **Exported Variables**: Use `snake_case`. (e.g., `@export var max_health: int`). The Inspector automatically converts this to Title Case ("Max Health").
- **Internal / Private Members**: Prepend a single underscore `_` to variables and methods that are internal to the class. (e.g., `var _current_health`, `func _calculate_damage()`). This also applies to virtual engine callbacks (e.g., `_ready`, `_process`).
- **Signals**: Use **past-tense** `snake_case` to represent events that have already occurred. (e.g., `signal health_changed`, `signal door_opened`).
- **Unique Names**: Use `%SceneUniqueNames` for frequently accessed nodes to avoid brittle `get_node()` paths.

### 2. Feature-Based Organization
Instead of grouping by *type* (e.g., `/scripts`, `/sprites`), group by *feature* (the "What", not the "How").

**Correct Structure:**
```
/project.godot
/common/           # Global resources, themes, shared scripts
/entities/
    /player/       # Everything related to player
        player.tscn
        player.gd
        player_sprite.png
    /enemy/
/ui/
    /main_menu/
/levels/
/addons/           # Third-party plugins
```

### 3. Version Control
- Always include a `.gitignore` tailored for Godot (ignoring `.godot/` folder and import artifacts).
- Use `.gdignore` in folders that Godot should not scan/import (e.g., raw design source files).

## Workflow: Scaffolding a New Project

When asked to "Setup a project" or "Start a new game":

1. **Initialize Root**: Ensure `project.godot` exists.
2. **Create Core Folders**:
   - `entities/`
   - `ui/`
   - `levels/`
   - `common/`
3. **Setup Git**: Create a comprehensive `.gitignore`.
4. **Documentation**: Create a `README.md` explaining the feature-based structure.

## ๐Ÿ”„ Migration Guide: Typed GDScript 2.0

Transitioning from untyped GDScript or C# to strictly-typed GDScript 2.0.

### 1. The Inference Operator (`:=`)
Use `:=` when the type is obvious from the right-hand side.
- **Good**: `var pos := Vector2(10, 10)`
- **Redundant**: `var pos: Vector2 = Vector2(10, 10)`

### 2. Typed Collections
Godot 4 introduces statically typed arrays and dictionaries.
- **Array**: `var enemies: Array[Enemy] = []`
- **Dictionary**: `var spawn_rates: Dictionary[StringName, float] = {}`

### 3. Explicit Return Types
Always specify the return type, even if it is `void`.
- `func take_damage(amount: int) -> void:`

### 4. Safe Casting (`as`)
Use the `as` keyword to guarantee a type and get "safe lines" (green line numbers in the editor).
- `var timer := $Timer as Timer`

### 5. Enforce Strictness
In **Project Settings > Debug > GDScript**, set **Untyped Declaration** to `Warn` or `Error`.

## Expert Foundation Architectures

### 1. Scene Transition Manager (Threaded)
Avoid blocking the main thread during scene changes by using `ResourceLoader.load_threaded_request()`. This allows you to show an animated loading screen while the background thread parses the next level.

```gdscript
class_name SceneManager extends Node
## Autoload: Manages threaded scene transitions.

signal progress_updated(percent: float)
var _target_path: String = ""

func load_scene(path: String) -> void:
    _target_path = path
    if ResourceLoader.load_threaded_request(path) == OK:
        set_process(true)

func _process(_delta: float) -> void:
    var progress := []
    var status := ResourceLoader.load_threaded_get_status(_target_path, progress)
    
    match status:
        ResourceLoader.THREAD_LOAD_IN_PROGRESS:
            progress_updated.emit(progress[0] * 100)
        ResourceLoader.THREAD_LOAD_LOADED:
            var scene := ResourceLoader.load_threaded_get(_target_path) as PackedScene
            get_tree().change_scene_to_packed(scene)
            set_process(false)
```

### 2. Global Event Bus (Decoupled)
Maintain strict decoupling by using a global "Event Bus" Autoload. This allows distant systems (e.g., UI and Boss AI) to communicate without knowing each other's existence.

```gdscript
class_name EventBus extends Node
## Autoload: Central hub for global signals.

signal player_died
signal quest_completed(quest_id: String)
signal boss_phase_changed(new_phase: int)

# Usage (Publisher):
# EventBus.player_died.emit()

# Usage (Subscriber):
# EventBus.player_died.connect(_on_player_death)
```

### 3. Project Metadata (Resource-Based)
Centralize project info like versioning, build dat

Related in General