godot-signals-groups
>
Works with
Claude CodeCursorCodex CLIGitHub CopilotGemini CLI
---
name: godot-signals-groups
description: >
license: Apache-2.0
---
# 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
```gdscript
# 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()
```
```gdscript
# 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
```gdscript
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
```gdscript
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:
```gdscript
func _ready() -> void:
add_to_group("enemies") # remove_from_group("enemies") to leave
```
### 4. Await a signal inline
```gdscript
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.** Disconnect long-lived listeners, or rely on
Godot auto-disconnecting when the *connected object* is freed (it does for nodes).
- **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.** Emitting with the wrong arg count/types raises an error;
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.More General & Other skills
find-skills
vercel-labs/skills
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
1.5M
grill-me
mattpocock/skills
A relentless interview to sharpen a plan or design.
972.7k
grill-with-docs
mattpocock/skills
A relentless interview to sharpen a plan or design, which also creates docs (ADR's and glossary) as we go.
828.8k

