概要
Godotで開発を進めていると、ノード同士が連 携する必要が出てきます。「プレイヤーがコインに触れたら、コインは消え、UIのスコアが上がる」といった場面です。初心者がやりがちなのは、プレイヤーのスクリプトからコインやUIのノードを直接参照(get_node()や$を使う)してしまうことです。しかし、この方法はノード間の依存関係を強め、後々の変更を非常に困難にします。
この問題を解決し、ノード同士を「疎結合」に保つためのGodotの根幹的な仕組みがシグナル (Signals) です。
シグナルとは?「イベントが発生したよ!」という合図
シグナルとは、あるノードが「特定のイベントが発生した」ことを、他のノードに知らせるためのメッセージ(合図)です。シグナルを発信する側(Emitter)は、誰がそのメッセージを受け取るかを知る必要はありません。ただ合図を送るだけです。
一方、メッセージを受け取りたい側(Receiver)は、特定のノードの特定のシグナルを「購読(Connect)」しておきます。これにより、シグナルが発信されたときに、自身の特定のメソッド(Callback)が自動的に呼び出されます。
この仕組みにより、EmitterとReceiverは直接お互いを知らなくても連携できるのです。これは「関心の分離」として知られる、優れたソフトウェア設計の基本原則です。
シグナルの使い方:エディタでの接続
最も簡単で視覚的な方法は、Godotエ ディタを使ってシグナルを接続することです。
-
シグナルを発信するノードを選択: シーンツリーで、シグナルを持つノード(例:
Buttonノード)を選択します -
「ノード」タブを開く: インスペクタの隣にある「ノード」タブを開き、その中の「シグナル」タブを選択します。すると、そのノードが発信できるシグナルの一覧が表示されます(例:
pressed()) -
シグナルを接続: 接続したいシグナル(例:
pressed())をダブルクリックします。すると「シグナルを接続」ダイアログが開きます -
受信者とメソッドを選択: ダイアログで、シグナルを受け取るノード(Receiver)を選択し、呼び出されるメソッド名を決定します(通常は自動生成される名前でOK)。「接続」ボタンを押せば完了です
これにより、Receiver側のスクリプトに、指定した名前のメソッドが自動的に生成されます。あとはそのメソッド内に、シグナルを受け取ったときの処理を記述するだけです。
# Receiver側のスクリプトに自動生成される
func _on_button_pressed():
print("ボタンが押されました!")
# ここに実行したい処理を書く
カスタムシグナルの定義と発信
Buttonのpressedのように組み込みのシグナルだけでなく、自分で独自のシグナルを定義することも 非常に重要です。
1. シグナルの定義: スクリプトの冒頭でsignalキーワードを使ってカスタムシグナルを宣言します。引数を渡すことも可能です。
# Player.gd
extends CharacterBody2D
# "health_changed"という名前のカスタムシグナルを定義
# 新しいHPの値を引数として渡せるようにする
signal health_changed(new_health)
var health = 100
func take_damage(amount):
health -= amount
# シグナルを発信する(Emitする)
health_changed.emit(health)
if health <= 0:
die()
2. シグナルの発信: シグナルを発信したいタイミングで、signal_name.emit()メソッドを呼び出します。定義時に引数を指定した場合は、emit()にその値を渡します。
3. 接続: このカスタムシグナルも、組み込みシグナルと全く同じように、エディタの「ノード」タブから他のノード(例: UIのHPバー)に接続できます。HPバーのスクリプトは、health_changedシグナルを受け取ったら、渡されたnew_healthの値を使って表示を更新するだけで済みます。プレイヤーがどうやってダメージを受けたか、といった詳細を知る必要はありません。
まとめ
シグナルは、Godotにおけるノード間連携の最もクリーンで推奨される方法です。
- 発信する側: 「イベントが起きた」と叫ぶだけ。誰が聞いているかは気にしない
- 受信する側: 聞きたい合図を登録しておき、呼ばれたら自分の仕事をするだけ
この疎結合な関係を意識してコンポーネントを設計することで、シーンの再利用性が高まり、バグが少なく、変更に強いプロジェクトを構築できます。get_node()で親や兄弟を直接参照するコードを書いてしまったら、「これはシグナルで実現できないか?」と一度立ち止まって考えてみる癖をつけることが、Godotマスターへの第一歩です。