godot-signals-groups について
Godot 4.7 の開発者向けに、シグナルとグループでノードを疎結合にする方法を解説するスキルガイドです。接続パターンや一括処理、よくある問題を扱います。
主な機能
- 01型付きシグナルによるイベント通知
- 02Callable を使ったシグナル接続
- 03グループを介した一括呼び出し
- 04シグナルを待ってから処理を続行
- 05重複接続や無効なリスナーの回避
活用シーン
- 01アイテム取得をゲーム状態へ通知
- 02敵グループの一括停止や数の確認
- 03アニメーション完了後の戦利品生成
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ gamedev-skills/ awesome-gamedev-agent-skills --skill godot-signals-groupsインストール後、Claude Code で/godot-signals-groupsを入力して読み込まれたか確認します。
同梱ファイルreferences/signal-patterns.md
詳細
Godot Signals & Groups (4.x)
オブザーバーパターン(シグナル)とグループを使ってノードを疎結合にし、シーン間で参照をハードコードすることなく、複数のノードに一度に処理を実行します。対象は Godot 4.7 です。
使用する場面
- ノードが他のノードを直接参照せずに、「何かが起きた」こと(プレイヤーの死亡、アイテムの取得、ウェーブのクリアなど)を伝える必要がある場合に使用します。
- ノード全体のカテゴリに一度に処理を実行する必要がある場合(「敵をすべて一時停止する」「すべてのチェックポイントを保存する」など)に使用します。
使用しない場面: シグナルの基本的な 構文 → godot-gdscript。シーン構造とインスタンス化 → godot-nodes-scenes。シーンをまたぐグローバルイベントには、オートロードから発行してください(godot-nodes-scenes を参照)。
基本的なワークフロー
- 方向を決めます。 子ノード/サブシーンはシグナルを上位に向けて 発行 し、親ノードが接続します。これにより、子ノードは再利用可能になり、誰がリッスンしているかを知る必要がなくなります。
- 発行側で型付きシグナルを宣言し、イベント発生時に
emit()で発行します。 - Callable で接続します(
sig.connect(_on_sig))。必要に応じて、エディターの Node ドックから接続することもできます。1 回だけ実行する場合はCONNECT_ONE_SHOTを使い、追加のコンテキストを渡す場合はbind()を使います。 - ブロードキャストにはグループを使います。 ノードを名前付きグループに追加し、
get_tree().get_nodes_in_group(...)で反復処理するか、call_group(...)を呼び出します。 - 必要に応じて(長寿命のリスナーを解放する前などに)接続を解除し、重複接続を避けるために
is_connected()を確認します。
パターン
1. 上位に向けて発行し、親から接続する
# 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. 接続フラグ:1 回限りの接続と追加引数のバインド
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. グループ:複数のノードにブロードキャストする
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()
コードから、またはエディターの Node > Groups タブからノードをグループに追加します。
func _ready() -> void:
add_to_group("enemies") # remove_from_group("enemies") to leave
4. シグナルをインラインで待機する
func open_chest() -> void:
$AnimationPlayer.play("open")
await $AnimationPlayer.animation_finished # pause until it emits
spawn_loot()
注意点
- 3.x の connect シグネチャは使えません。
connect("died", self, "_on_died")→died.connect(_on_died)。接続先は Callable によって示されます。旧式のObject.connect("died", Callable(self, "_on_died"))は動作しますが、メソッド名を文字列で指定する形式は使えません。 - 接続が重複すると、ハンドラーが複数回実行されます。 ノードを再追加した後に
_ready()で再接続すると、コールバックが積み重なります。if not sig.is_connected(cb): sig.connect(cb)で防止します。 - 解放済みのノードへの接続はエラーになります。 長寿命のリスナーは接続を解除するか、接続先のオブジェクトが解放された際に Godot が自動で接続を解除する仕組みを利用します(ノードでは自動的に解除されます)。
- グループはシーンごとではなく SceneTree 全体で共有されます。 同じグループ名を使う 2 つのレベルは、メンバーシップを共有します。必要に応じて、グループ名に名前空間を設けてください。
call_groupは、対象のメソッドを持たないノードを黙って無視します。 メソッド名の誤りは通知されずに失敗するため、契約が重要な場合は型付きシグナルを優先してください。- シグナルの引数は一致している必要があります。 引数の数や型を誤って発行するとエラーになります。型付きパラメーターを宣言し、正確な引数を指定して発行してください。
参考資料
- 接続フラグ、遅延接続、カスタムシグナル引数、タイムアウト付きの待機、シグナルと直接呼び出しの使い分けについては、
references/signal-patterns.mdを参照してください。
関連スキル
godot-gdscript— シグナル/await構文の基礎。godot-nodes-scenes— グローバルイベントバス用のオートロード。game-ai— これらのイベントを駆動・処理することの多いステートマシン。
コメント
Markdown 対応