Skip to content
Development
Skill

/event-bus

Use when setting up decoupled node communication — a global EventBus autoload with typed signals. Not for adding signals to an existing bus

From plugin
godot-prompter
96061 skills9 agents1 hook

Claude Code

$ npx -y skills add jame581/GodotPrompter --skill event-bus --agent claude-code

SKILL.md

event-bus.SKILL.md
name: event-bus
description: Use when setting up decoupled node communication — a global EventBus autoload with typed signals. Not for adding signals to an existing bus

Event Bus in Godot 4.3+

A global signal hub that lets unrelated nodes communicate without holding references to each other. All examples target Godot 4.3+ with no deprecated APIs.

> **Related skills:** **component-system** for direct signal communication between components, **csharp-signals** for C#-specific signal patterns, **dependency-injection** for alternative decoupling approaches, **ability-system** for an EventBus usage example with ability events.

---

1. What is an Event Bus

An EventBus is a singleton autoload that acts as a central registry for signals. Instead of nodes connecting directly to each other, every node connects to (or emits on) the shared EventBus. This removes the need for one node to hold a reference to another.

Without EventBus             With EventBus
──────────────               ──────────────────────────
NodeA ──signal──► NodeB      NodeA ──emit──► EventBus ──signal──► NodeB
                                                       ──signal──► NodeC
                                                       ──signal──► NodeD

**Flow diagram**

┌─────────┐   emit(player_died)   ┌───────────┐   player_died   ┌──────────┐
│  NodeA  │ ────────────────────► │ EventBus  │ ───────────────► │  NodeB   │
│(Player) │                       │(Autoload) │                  │   (UI)   │
└─────────┘                       └───────────┘ ───────────────► └──────────┘
                                                  player_died    ┌──────────┐
                                                                 │  NodeC   │
                                                                 │(AudioMgr)│
                                                                 └──────────┘

NodeA emits the signal. NodeB and NodeC each connected to EventBus independently. Neither knows the other exists.

---

2. When to Use vs Direct Signals

| Scenario | Recommended approach | |--------------------------------------------|-------------------------------| | Parent notifying its own child | Direct signal or method call | | Child notifying its parent | Direct signal (bubble up) | | Two nodes with the same parent | Direct signal via parent | | Completely unrelated nodes in the tree | Event bus | | UI reacting to gameplay state changes | Event bus | | Audio manager reacting to game events | Event bus | | Data manager / save system reacting | Event bus | | Tight, performance-sensitive inner loop | Direct method call |

**Rule of thumb:** if you would otherwise need `get_node("../../SomeDistantNode")` or a hard-coded NodePath, the event bus is a better fit.

---

3. Basic EventBus

Create `res://autoloads/event_bus.gd` (or `EventBus.cs`), then register it in **Project → Project Settings → Globals → Autoload** with the name `EventBus`.

GDScript (`autoloads/event_bus.gd`)

extends Node

## Emitted when the player character has died.
signal player_died

## Emitted whenever the score changes.
signal score_changed(new_score: int)

## Emitted when a level finishes successfully.
signal level_completed(level_id: int)

## Emitted when the player picks up a collectible.
signal item_collected(item_name: String)

## Emitted when the player's health changes.
signal health_changed(current: int, maximum: int)

C# (`Autoloads/EventBus.cs`)

using Godot;

/// <summary>
/// Global signal hub. Register as an autoload named "EventBus".
/// </summary>
public partial class EventBus : Node
{
    /// <summary>Emitted when the player character has died.</summary>
    [Signal] public delegate void PlayerDiedEventHandler();

    /// <summary>Emitted whenever the score changes.</summary>
    [Signal] public delegate void ScoreChangedEventHandler(int newScore);

    /// <summary>Emitted when a level finishes successfully.</summary>
    [Signal] public delegate void LevelCompletedEventHandler(int levelId);

    /// <summary>Emitted when the player picks up a collectible.</summary>
    [Signal] public delegate void ItemCollectedEventHandler(string itemName);

    /// <summary>Emitted when the player's health changes.</summary>
    [Signal] public delegate void HealthChangedEventHandler(int current, int maximum);
}

---

4. Connecting to Events

Consumers connect in `_ready()`. In C#, always disconnect in `_ExitTree()`: the bus outlives its consumers and its signals are custom, a case Godot does not disconnect when the consumer is freed, so the next emit would throw `ObjectDisposedException`.

GDScript

extends CanvasLayer

# A connection to this node's method is removed automatically when the
# node is freed, but explicit disconnection is still good practice
# for long-lived nodes that reconnect frequently.

func _ready() -> void:
    EventBus.player_died.connect(_on_player_died)
    EventBus.score_changed.connect(_on_score_changed)
    EventBus.health_changed.connect(_on_health_changed)


func _exit_tree() -> void:
    EventBus.player_died.disconnect(_on_player_died)
    EventBus.score_changed.disconnect(_on_score_changed)
    EventBus.health_changed.disconnect(_on_health_changed)


func _on_player_died() -> void:
    $DeathScreen.show()


func _on_score_changed(new_score: int) -> void:
    $ScoreLabel.text = "Score: %d" % new_score


func _on_health_changed(current: int, maximum: int) -> void:
    $HealthBar.value = float(current) / float(maximum) * 100.0

C#

using Godot;

public partial class HudLayer : CanvasLayer
{
    private EventBus _eventBus;

    public override void _Ready()
    {
        _eventBus = GetNode<EventBus>("/root/EventBus");

        // Connect using strongly-typed delegate handlers
        _eventBus.PlayerDied      += OnPlayerDied;
        _eventBus.ScoreChanged    += OnScoreChanged;
        _eventBus.HealthChanged   += OnHealthCha
Read more
@jame581
Ships withgodot-prompter

Agentic skills framework for Godot 4.x game development. Gives AI coding agents domain-specific expertise for GDScript and C# projects.

96061 skills9 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
960
Star history of jame581/GodotPrompter on GitHub, a chart by star-history.com

Other skills on godot-prompter.

2d-essentials

2d-essentials

Use when working with 2D-specific systems — TileMaps, parallax scrolling, 2D lights and shadows, canvas layers, particles 2D,…

3d-essentials

3d-essentials

Use when working with 3D-specific systems — materials, lighting, shadows, environment, global illumination, fog, LOD, occlusion…

ability-system

ability-system

Use when building or replacing an ability system — abilities with cost/cooldown, buffs/debuffs, stat modifiers, and gameplay…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills13d309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react4d252k
@facebook@facebookInstall Skill

Questions about event-bus.

Which coding agents can use event-bus?
event-bus installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.