Skip to content

moore-austin/event-bus

Repository files navigation

Godot Strategic Event Bus

Overview

This module implements a Global Event Bus (Signal Bus) pattern for Godot 4.x. It serves as a central nervous system for your game, allowing distant nodes (e.g., a Trap in a level and a HealthBar in the UI) to communicate without Topology Coupling or Location Dependency.

By using this module, you eliminate the need for brittle get_node() paths that span across scene boundaries, significantly reducing Change Amplification when refactoring scene hierarchies.

Philosophy

  • Deep Module Design: Encapsulates the complexity of global state management behind the native, simple interface of Godot signals.
  • Strict Typing: Rejects string-based event lookups in favor of first-class signals to prevent "Unknown Unknowns" (silent failures due to typos).
  • Zero-Lazy-Code: Includes a built-in debug monitor to visualize signal traffic without requiring manual print statements.

🛠 Integration Guide

To integrate this module into your Godot project, you must register it as an Autoload (Singleton). This ensures the bus is accessible from every script in your game.

  1. Save the Script:
    Save the provided code as events.gd in a logical location, such as res://scripts/globals/events.gd. Note: file names must use snake_case.
  2. Open Project Settings:
    Go to Project -> Project Settings... in the top menu.
  3. Navigate to Autoload:
    Click the Globals tab (labeled Autoload in some versions).
  4. Add the Script:
    • Path: Click the folder icon and select your events.gd file.
    • Node Name: Ensure the name is set to Events (PascalCase). This is the global variable name you will use in code.
    • Global Variable: Ensure the "Enable" checkbox is checked.
    • Click Add.

🚀 Usage Guide

1. Defining Events

Unlike generic plugins that use loose strings, this strategic approach requires you to explicitly define your signals in events.gd. This serves as self-documenting code for your game's architecture.

Open events.gd and add signals at the top:

# events.gd

# Define your project-specific events here
signal player_health_changed(new_health: int, max_health: int)
signal item_collected(item_type: StringName)
signal level_completed

2. The Sender (Emitting)

Any node can shout a message to the bus. The sender does not need to know who is listening.

# player.gd
func take_damage(amount: int) -> void:
health -= amount
# Strategic: The player doesn't know the UI exists. It just reports the data.
Events.player_health_changed.emit(health, max_health)

3. The Receiver (Listening)

Any node can listen for messages. The receiver does not need to know where the sender is located.

# health_bar.gd
func _ready() -> void:
# Strategic: Connection is type-safe. If the signal name changes,
# the editor will throw an error (Preventing Unknown Unknowns).
Events.player_health_changed.connect(_update_display)

func _update_display(new_val: int, max_val: int) -> void:
value = new_val

🔧 Debugging Features

The module includes a toggleable debug logger. When enabled, it prints all global signal emissions to the Output console with rich text formatting.

To enable/disable:

  1. Open events.gd.
  2. Change the const _VERBOSE_DEBUG to true or false.

Output Example:

[EventBus] Signal Emitted: player_health_changed | Payload: [80, 100]
[EventBus] Signal Emitted: item_collected | Payload: ["KeyCard"]

⚠️ Architectural Rules

  1. Do not use for local communication: If a parent node needs to talk to its direct child, use get_node() or an @onready reference. If a child needs to talk to its direct parent, use a standard signal. Only use Events for nodes that are "strangers" or distant in the Scene Tree.
  2. Maintain Naming Conventions: Signals should use snake_case and past tense (e.g., door_opened, not DoorOpen) to clearly indicate an event that has already happened.
  3. Strict Types: Always strictly type your signal parameters in the events.gd definition to ensure autocomplete works correctly.

About

The Global Event Bus (Autoload) Acts as a central nervous system for distant nodes to communicate without coupling. Follows the "Observer" pattern.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors