# Scene Organization

> Use when designing scene tree structure — composition vs inheritance, when to split scenes, node hierarchy patterns

- **Type:** Skill
- **Install:** `agentstack add skill-jame581-godotprompter-scene-organization`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [jame581](https://agentstack.voostack.com/s/jame581)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [jame581](https://github.com/jame581)
- **Source:** https://github.com/jame581/GodotPrompter/tree/master/skills/scene-organization

## Install

```sh
agentstack add skill-jame581-godotprompter-scene-organization
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Scene Organization

A guide for structuring Godot 4.3+ scene trees: when to split, when to compose, and how nodes should communicate.

> **Related skills:** **component-system** for composition patterns, **event-bus** for decoupled communication, **godot-brainstorming** for scene tree planning, **2d-essentials** for TileMapLayer and CanvasLayer organization.

---

## 1. Core Principle

Scenes are building blocks. Each scene encapsulates exactly one concept — a player, an enemy, a health bar, a weapon. A scene should be understandable in isolation, reusable without modification, and replaceable without breaking its neighbors.

> One scene = one responsibility. If you struggle to name a scene in two words or fewer, it is probably doing too much.

---

## 2. Composition Over Inheritance

### Player Scene — Composed from Reusable Parts

```
Player (CharacterBody2D)
├── Sprite2D
├── CollisionShape2D
├── HealthComponent
├── HitboxComponent
├── StateMachine
└── AnimationPlayer
```

`HealthComponent`, `HitboxComponent`, and `StateMachine` are separate `.tscn` files instantiated as child scenes. Any entity that needs health — enemy, destructible crate, boss — can include `HealthComponent` without duplicating logic.

### HealthComponent — Full Example

**GDScript**

```gdscript
# health_component.gd
class_name HealthComponent
extends Node

signal health_changed(old_value: int, new_value: int)
signal died

@export var max_health: int = 100

var current_health: int

func _ready() -> void:
    current_health = max_health

func take_damage(amount: int) -> void:
    if amount  void:
    if amount  bool:
    return current_health > 0
```

**C#**

```csharp
// HealthComponent.cs
using Godot;

[GlobalClass]
public partial class HealthComponent : Node
{
    [Signal]
    public delegate void HealthChangedEventHandler(int oldValue, int newValue);

    [Signal]
    public delegate void DiedEventHandler();

    [Export]
    public int MaxHealth { get; set; } = 100;

    public int CurrentHealth { get; private set; }

    public override void _Ready()
    {
        CurrentHealth = MaxHealth;
    }

    public void TakeDamage(int amount)
    {
        if (amount  CurrentHealth > 0;
}
```

### When to Use Inheritance Instead

Inheritance suits cases where scenes share **structure**, not just behavior — when child scenes are variations of the same thing with identical node layout and only a few exported properties differ.

Good candidates:

- `Enemy` → `Orc`, `Goblin` — same bones (Sprite2D, CollisionShape2D, HealthComponent, AI), different stats and art
- `Weapon` → `Sword`, `Bow` — same slot attachment logic, different animations and damage type
- `Pickup` → `HealthPickup`, `AmmoPickup` — same Area2D + CollisionShape2D + animation, different effect on collection

### Rule of Thumb

| Scenario | Pattern |
|---|---|
| You would copy-paste the entire scene and change a few exported properties | **Inheritance** |
| You want to mix and match a subset of nodes across different entity types | **Composition** |

---

## 3. Scene Splitting Rules

### Split a scene when:

- **Reuse** — the sub-scene is needed in more than one parent scene
- **Complexity** — the scene exceeds roughly 15 nodes; it is carrying more than one concern
- **Independence** — the sub-scene can be tested, previewed, or modified without opening its parent
- **Team** — separate scenes reduce merge conflicts when multiple people work on the same feature

### Keep nodes together when:

- Nodes are **tightly coupled** — splitting them would require excessive signal wiring just to replicate what a direct node reference handles cleanly
- The grouping is **small and used only once** — a two-node helper that exists in a single scene does not warrant its own `.tscn` file
- Splitting would create **simple-operation overhead** — if a parent must wire three signals just to tell a child "you were hit", the split is not paying for itself

---

## 4. Node Communication Patterns

```
        [Parent]
        /      \
  [Child A]  [Child B]
       \
     [Child C]
```

### Signals travel up (child → parent)

A child node announces that something happened. The parent — or any node that has connected to the signal — decides what to do about it. This keeps children ignorant of their context and fully reusable.

```gdscript
# Child emits; it does not know who is listening
health_component.died.connect(_on_player_died)
```

### Method calls travel down (parent → child)

A parent drives its children by calling their methods directly. The parent owns the reference; the child exposes a clean API and does not need to know about its parent.

```gdscript
# Parent calls into child
$HealthComponent.take_damage(10)
$AnimationPlayer.play("hurt")
```

### EventBus travels sideways (peer → peer)

For communication between scenes that have no ancestor–descendant relationship — e.g., an enemy notifying the HUD — use an Autoload event bus. Emitting on the bus decouples sender from receiver entirely.

```gdscript
# Autoload: EventBus.gd
signal enemy_killed(enemy: Enemy)

# Enemy scene
EventBus.enemy_killed.emit(self)

# HUD scene
EventBus.enemy_killed.connect(_on_enemy_killed)
```

**C#**

```csharp
// Pattern 1: Signals travel up (child → parent)
// Child emits; it does not know who is listening.
public partial class Player : CharacterBody2D
{
    public override void _Ready()
    {
        var health = GetNode("HealthComponent");
        health.Died += OnPlayerDied;
    }

    private void OnPlayerDied()
    {
        // Parent reacts — child HealthComponent stays ignorant of context
    }
}

// Pattern 2: Method calls travel down (parent → child)
// Parent drives children by calling their methods directly.
public partial class Level : Node2D
{
    public override void _Ready()
    {
        var health = GetNode("Player/HealthComponent");
        health.TakeDamage(10);

        var anim = GetNode("Player/AnimationPlayer");
        anim.Play("hurt");
    }
}

// Pattern 3: EventBus travels sideways (peer → peer)
// EventBus.cs — registered as an Autoload singleton named "EventBus"
public partial class EventBus : Node
{
    [Signal] public delegate void EnemyKilledEventHandler(Enemy enemy);
}

// Enemy scene — emits on the bus; does not reference HUD
public partial class Enemy : CharacterBody2D
{
    private void Die()
    {
        var bus = GetNode("/root/EventBus");
        bus.EmitSignal(EventBus.SignalName.EnemyKilled, this);
        QueueFree();
    }
}

// HUD scene — subscribes on the bus; does not reference Enemy
public partial class Hud : CanvasLayer
{
    public override void _Ready()
    {
        var bus = GetNode("/root/EventBus");
        bus.EnemyKilled += OnEnemyKilled;
    }

    private void OnEnemyKilled(Enemy enemy)
    {
        // Update kill counter, score, etc.
    }
}
```

---

## 5. Scene Tree Patterns

### Entity-Component Pattern

```
Enemy (CharacterBody2D)
├── Visuals
│   ├── Sprite2D
│   └── AnimationPlayer
├── Collision
│   └── CollisionShape2D
├── Components
│   ├── HealthComponent
│   └── HitboxComponent
└── AI
    ├── NavigationAgent2D
    └── StateMachine
```

Group by concern using plain `Node` containers (`Visuals`, `Collision`, `Components`, `AI`). Each sub-group can be collapsed in the editor and worked on independently.

### UI Scene Pattern

```
HUD (CanvasLayer)
├── MarginContainer
│   ├── TopBar
│   │   ├── HealthBar
│   │   └── ResourceBar
│   └── BottomBar
│       ├── Hotbar
│       └── MiniMap
└── PauseMenu
```

`CanvasLayer` ensures HUD elements are always rendered on top. `MarginContainer` handles safe-area padding. `TopBar`, `BottomBar`, and `PauseMenu` are separate instantiated scenes so each can be edited without opening the root HUD scene.

### Level Scene Pattern

```
Level01 (Node2D)
├── TileMapLayer
├── Entities
│   ├── Player (instance)
│   └── Enemies (Node2D)
│       ├── Orc (instance)
│       └── Goblin (instance)
├── Pickups (Node2D)
├── Navigation
│   └── NavigationRegion2D
└── Camera2D
```

The level scene is a composition root — it owns the layout and spawns instances, but contains no gameplay logic itself. `Entities`, `Pickups`, and `Navigation` are plain `Node2D` containers used for organizational grouping and to simplify `get_children()` iteration.

---

## 6. Checklist

- [ ] Each scene has exactly one responsibility, named in two words or fewer
- [ ] Reusable components (`HealthComponent`, `StateMachine`, etc.) are separate `.tscn` files
- [ ] No scene exceeds ~15 nodes without a documented reason to keep it together
- [ ] Children emit signals upward; parents call methods downward
- [ ] Peer-to-peer communication uses an EventBus Autoload, not `get_parent()` chains
- [ ] No `get_parent().get_parent()` or `get_node("../../SomeNode")` paths in code
- [ ] Nodes are grouped into logical containers (`Visuals`, `Components`, `AI`, etc.) for readability

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [jame581](https://github.com/jame581)
- **Source:** [jame581/GodotPrompter](https://github.com/jame581/GodotPrompter)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-jame581-godotprompter-scene-organization
- Seller: https://agentstack.voostack.com/s/jame581
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
