Skip to content
Development
Skill

/godot-signals-groups

Build event-driven, decoupled Godot 4.7 gameplay with signals and node groups: declare and emit custom signals, connect with Callables (incl. bind/one-shot), and broadcast to many nodes via groups and call_group. Use when wiring node communication in a Godot project, replacing

From plugin
awesome-gamedev-agent-skills
6.3k77 skills

Claude Code

$ npx -y skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-signals-groups --agent claude-code

SKILL.md

godot-signals-groups.SKILL.md
name: godot-signals-groups
description: >
  Build event-driven, decoupled Godot 4.7 gameplay with signals and node groups:
  declare and emit custom signals, connect with Callables (incl. bind/one-shot),
  and broadcast to many nodes via groups and call_group. Use when wiring node
  communication in a Godot project, replacing tight references with signals,
  emitting/connecting events, or porting 3.x connect("sig", self, "method") code.

Godot Signals & Groups (4.x)

Decouple nodes with the observer pattern (signals) and act on many nodes at once (groups), instead of hard-coding references between scenes. Targets **Godot 4.7**.

When to use

  • Use when a node needs to tell others "something happened" (player died, item picked

up, wave cleared) without holding direct references to them.

  • Use when you need to address a whole category of nodes at once ("pause all enemies",

"save every checkpoint").

**When *not* to use:** raw signal *syntax* basics → `godot-gdscript`; scene structure and instancing → `godot-nodes-scenes`. For cross-scene global events, emit from an autoload (see `godot-nodes-scenes`).

Core workflow

1. **Decide the direction.** A child/sub-scene should *emit* a signal upward; the parent *connects* to it. This keeps the child reusable and ignorant of who listens. 2. **Declare typed signals** on the emitter; `emit()` them when the event occurs. 3. **Connect with a Callable** (`sig.connect(_on_sig)`), optionally in the editor's Node dock. Use `CONNECT_ONE_SHOT` for fire-once, `bind()` to pass extra context. 4. **Use groups for broadcast**: add nodes to a named group, then iterate `get_tree().get_nodes_in_group(...)` or `call_group(...)`. 5. **Disconnect when needed** (e.g. before freeing a long-lived listener) and check `is_connected()` to avoid duplicate connections.

Patterns

1. Emit upward, connect from the parent

# coin.gd (reusable pickup — knows nothing about the player or HUD)
extends Area2D
signal collected(value: int)

func _on_body_entered(body: Node) -> void:
    if body.is_in_group("player"):
        collected.emit(10)
        queue_free()
# level.gd (the parent wires the coin to game state)
func _ready() -> void:
    for coin in get_tree().get_nodes_in_group("coins"):
        coin.collected.connect(_on_coin_collected)

func _on_coin_collected(value: int) -> void:
    GameState.add_score(value)

2. Connect flags: one-shot and bind extra arguments

func _ready() -> void:
    # Fire exactly once, then auto-disconnect.
    $Door.opened.connect(_on_door_opened, CONNECT_ONE_SHOT)
    # bind() appends arguments supplied at connect time (after the signal's own args).
    $RedButton.pressed.connect(_on_button.bind("red"))

func _on_button(color: String) -> void:
    print("Pressed the %s button" % color)

3. Groups: broadcast to many nodes

func pause_all_enemies() -> void:
    # Call a method on every node in the "enemies" group (no-op if missing).
    get_tree().call_group("enemies", "set_paused", true)

func count_enemies() -> int:
    return get_tree().get_nodes_in_group("enemies").size()

Add a node to a group from code or via the editor's Node > Groups tab:

func _ready() -> void:
    add_to_group("enemies")        # remove_from_group("enemies") to leave

4. Await a signal inline

func open_chest() -> void:
    $AnimationPlayer.play("open")
    await $AnimationPlayer.animation_finished   # pause until it emits
    spawn_loot()

Pitfalls

  • **3.x connect signature is gone.** `connect("died", self, "_on_died")` →

`died.connect(_on_died)`. The target is implied by the Callable. The legacy `Object.connect("died", Callable(self, "_on_died"))` works but the method-name string form does not.

  • **Duplicate connections fire handlers multiple times.** Connecting again in `_ready()`

after re-adding a node stacks callbacks. Guard with `if not sig.is_connected(cb): sig.connect(cb)`.

  • **Connecting to a freed node errors.** Godot removes a connection when the emitter or

the Callable's owner is freed, but a lambda belongs to the script that created it — one that captures a node freed later keeps firing and errors. Connect listener methods, or disconnect stored lambdas yourself.

  • **Groups are global to the SceneTree**, not per-scene. Two levels using the same group

name share membership. Namespace group names if that matters.

  • **`call_group` silently ignores nodes lacking the method.** Typos in the method name

fail quietly — prefer a typed signal when the contract matters.

  • **Signal args must match the handlers.** `emit()` does not validate arguments against

the `signal` declaration; a handler with a different argument count fails with "Method expected N argument(s)" at emit time. Declare typed params and emit exactly those.

References

  • For connection flags, deferred connections, custom signal arguments, awaiting with

timeouts, and signals vs. direct calls trade-offs, read `references/signal-patterns.md`.

Related skills

  • `godot-gdscript` — signal/`await` syntax fundamentals.
  • `godot-nodes-scenes` — autoloads for global event buses.
  • `game-ai` — state machines that often drive and consume these events.
Read more
@gamedev-skills
Ships withawesome-gamedev-agent-skills

<img src="docs/assets/awesome-gamedev-agent-skills-banner.png" width="820" alt="awesome-gamedev-agent-skills — game-dev skills for AI coding agents.

Stars on GitHub

Momentum

stars in total
6.3k
Star history of gamedev-skills/awesome-gamedev-agent-skills on GitHub, a chart by star-history.com

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.

skills10d309k
@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,…

ecc12d293k
@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…

react1d252k
@facebook@facebookInstall Skill

Questions about godot-signals-groups.

Which coding agents can use godot-signals-groups?
godot-signals-groups 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.