Godot 4 Signal Patterns — Complete Guide

Godot 4 シグナルパターン — 完全ガイド

1. Introduction — What Changed in Godot 4

1. はじめに — Godot 4で何が変わったか

Godot 4 completely overhauled how signals work. If you're coming from Godot 3, the old string-based object.connect("signal_name", target, "method_name") syntax is gone. In its place, Godot 4 uses a callable-based API that is type-safe, refactor-friendly, and catches errors at compile time instead of runtime.

Godot 4ではシグナルの仕組みが大幅に刷新されました。Godot 3の文字列ベースの object.connect("signal_name", target, "method_name") 構文は廃止され、代わりにCallable(呼び出し可能オブジェクト)ベースのAPIが導入されました。型安全でリファクタリングしやすく、実行時ではなくコンパイル時にエラーを検出できます。

This guide covers everything you need to know about signals in Godot 4.4+: declaring, connecting, disconnecting, emitting, awaiting, and the most useful real-world patterns.

このガイドでは、Godot 4.4+のシグナルについてすべてを解説します:宣言、接続、切断、発火、await、そして実践的なパターンまで。

Key Takeaway
ポイント

In Godot 4, signals are first-class objects. You access them as properties (e.g., button.pressed) and call methods on them (.connect(), .emit(), .disconnect()). No more string-based API.

Godot 4では、シグナルは第一級オブジェクトです。プロパティとしてアクセスし(例:button.pressed)、メソッドを呼び出します(.connect().emit().disconnect())。文字列ベースのAPIはもう不要です。

2. Declaring Custom Signals

2. カスタムシグナルの宣言

Declare signals at the top of your script with the signal keyword. You can optionally specify parameter names and types for documentation and editor autocomplete.

スクリプトの先頭で signal キーワードを使ってシグナルを宣言します。ドキュメントやエディタの自動補完のために、パラメータ名と型を指定することもできます。

player.gd
# Simple signal with no parameters
signal game_over

# Signal with typed parameters
signal health_changed(new_health: int)

# Signal with multiple parameters
signal item_picked_up(item_name: String, quantity: int)

# Signal with no type hints (works, but typed is recommended)
signal something_happened(data)
Tip
ヒント

Always add type hints to signal parameters. This enables autocomplete in the editor and makes your code self-documenting. Signals with type hints also show parameter info in the Signals tab of the Node dock.

シグナルのパラメータには常に型ヒントを追加しましょう。エディタでの自動補完が有効になり、コードが自己文書化されます。型ヒント付きのシグナルは、ノードドックのシグナルタブでもパラメータ情報が表示されます。

3. Connecting Signals (The New Way)

3. シグナルの接続(新しい方法)

The biggest change in Godot 4 is how you connect signals. Instead of passing strings, you use the signal as a property and call .connect() with a Callable (a reference to a function).

Godot 4で最大の変更点はシグナルの接続方法です。文字列を渡す代わりに、シグナルをプロパティとして使い、Callable(関数への参照)を引数に .connect() を呼び出します。

Basic Connection

基本的な接続

GDScript
# Godot 3 (OLD — no longer works in Godot 4)
# button.connect("pressed", self, "_on_button_pressed")

# Godot 4 — callable-based connection
button.pressed.connect(_on_button_pressed)

func _on_button_pressed() -> void:
    print("Button was pressed!")

Connection with Extra Arguments via bind()

bind()による追加引数付き接続

Use .bind() to pass extra data along with the signal. This is useful when connecting multiple signals to the same method.

.bind() を使ってシグナルと一緒に追加データを渡せます。複数のシグナルを同じメソッドに接続するときに便利です。

GDScript
# Pass extra data via bind()
buy_button.pressed.connect(_on_item_button.bind("sword"))
sell_button.pressed.connect(_on_item_button.bind("shield"))

func _on_item_button(item_id: String) -> void:
    print("Selected item: ", item_id)

Lambda (Inline) Connections

ラムダ(インライン)接続

For short handlers, you can use a lambda function directly. This keeps simple logic close to the connection point.

短いハンドラーの場合、ラムダ関数を直接使えます。シンプルなロジックを接続箇所の近くに保てます。

GDScript
# Lambda — great for one-liners
button.pressed.connect(func(): print("Button pressed!"))

# Lambda with parameters
health_changed.connect(func(hp: int): health_label.text = str(hp))

# Multi-line lambda
enemy.died.connect(func():
    score += 100
    score_label.text = "Score: %d" % score
    print("Enemy defeated!")
)
Warning
注意

Lambda connections cannot be easily disconnected because you don't have a reference to the anonymous function. If you need to disconnect later, store the Callable in a variable or use a named method instead.

ラムダ接続は無名関数への参照がないため、簡単に切断できません。後で切断が必要な場合は、Callableを変数に保存するか、名前付きメソッドを使いましょう。

Connecting in the Editor (Node Dock)

エディタでの接続(ノードドック)

You can still connect signals through the Godot editor UI. Select a node, open the Node dock > Signals tab, double-click a signal, and choose the target node and method. The editor will auto-generate a method like _on_button_pressed() in your script. This is identical to calling .connect() in code — it just saves typing.

GodotエディタのUIからもシグナルを接続できます。ノードを選択し、ノードドック > シグナルタブを開いて、シグナルをダブルクリックし、接続先のノードとメソッドを選びます。エディタはスクリプトに _on_button_pressed() のようなメソッドを自動生成します。コードで .connect() を呼ぶのと同じ結果になります。

4. Disconnecting Signals

4. シグナルの切断

Disconnect a signal when you no longer want to receive it. This is important for avoiding errors when nodes are freed or when switching game states.

シグナルを受信したくなくなったら切断します。ノードが解放されたときやゲームステートが切り替わるときのエラー防止に重要です。

GDScript
# Disconnect a signal
button.pressed.disconnect(_on_button_pressed)

# Always check before disconnecting to avoid errors
if button.pressed.is_connected(_on_button_pressed):
    button.pressed.disconnect(_on_button_pressed)
Best Practice
ベストプラクティス

For cross-scene signal connections (e.g., connecting to an Autoload), always disconnect in _exit_tree() to prevent dangling references when the node is freed:

シーンをまたぐシグナル接続(Autoloadへの接続など)では、ノード解放時のダングリング参照を防ぐために、必ず _exit_tree() で切断しましょう:

GDScript
func _ready() -> void:
    EventBus.player_died.connect(_on_player_died)

func _exit_tree() -> void:
    if EventBus.player_died.is_connected(_on_player_died):
        EventBus.player_died.disconnect(_on_player_died)

5. Emitting Signals

5. シグナルの発火

In Godot 4, use .emit() instead of the old emit_signal(). The signal is an object, so you call the method directly on it.

Godot 4では、旧来の emit_signal() の代わりに .emit() を使います。シグナルはオブジェクトなので、直接メソッドを呼び出します。

player.gd
signal health_changed(new_health: int)
signal died

var health: int = 100

func take_damage(amount: int) -> void:
    health -= amount
    health_changed.emit(health)  # Emit with argument

    if health <= 0:
        died.emit()  # Emit with no arguments
Note
メモ

The old emit_signal("signal_name") still technically works in Godot 4 but is deprecated. Always prefer signal_name.emit() for new code. The string-based version may be removed in a future Godot release.

旧来の emit_signal("signal_name") はGodot 4でも技術的には動作しますが、非推奨です。新しいコードでは常に signal_name.emit() を使いましょう。文字列ベースのバージョンは将来のGodotリリースで削除される可能性があります。

6. Awaiting Signals

6. シグナルのawait

Godot 4 replaced yield() with await. This lets you pause a function until a signal fires, which is perfect for cutscenes, tutorials, sequential animations, and timed events.

Godot 4では yield()await に置き換わりました。シグナルが発火するまで関数を一時停止できるので、カットシーン、チュートリアル、連続アニメーション、タイマーイベントに最適です。

GDScript
func play_cutscene() -> void:
    # Wait for a timer
    await get_tree().create_timer(2.0).timeout

    # Wait for an animation to finish
    animation_player.play("intro")
    await animation_player.animation_finished

    # Wait for player input (custom signal)
    dialogue_label.text = "Press any key to continue..."
    await player_pressed_continue

    # Continue execution after the signal fires
    print("Cutscene complete!")

Getting Values from Awaited Signals

awaitしたシグナルから値を取得

If the signal emits arguments, await returns them. For a single argument, you get the value directly. For multiple arguments, you get an array.

シグナルが引数を発火する場合、await はそれらを返します。引数が1つなら値がそのまま返り、複数なら配列が返ります。

GDScript
# Single parameter — returns the value directly
var final_health: int = await health_changed
print("Health is now: ", final_health)

# Multiple parameters — returns an array
var result = await item_picked_up
var item_name: String = result[0]
var quantity: int = result[1]

7. Signal Connection Flags

7. シグナル接続フラグ

Godot provides connection flags as the second argument to .connect() that modify the behavior of the connection.

Godotは .connect() の第2引数として接続フラグを提供し、接続の動作を変更できます。

CONNECT_ONE_SHOT

The connection is automatically removed after the signal fires once. Perfect for one-time events like death animations or achievement unlocks.

シグナルが1回発火すると接続が自動で解除されます。デスアニメーションや実績アンロックなど、1回限りのイベントに最適です。

GDScript
# Auto-disconnects after firing once
enemy.died.connect(_on_first_kill, CONNECT_ONE_SHOT)

func _on_first_kill() -> void:
    unlock_achievement("first_blood")

CONNECT_DEFERRED

The connected method is called at the end of the current frame (during idle time) instead of immediately. Useful when the signal handler modifies the scene tree, which is not safe to do during physics or signal processing.

接続されたメソッドは、即座にではなく現在のフレームの最後(アイドル時間中)に呼び出されます。シグナルハンドラーがシーンツリーを変更する場合に便利で、物理処理やシグナル処理中にシーンツリーを変更するのは安全ではないためです。

GDScript
# Called at end of frame — safe for scene tree changes
button.pressed.connect(_on_restart, CONNECT_DEFERRED)

func _on_restart() -> void:
    get_tree().reload_current_scene()

Combining Flags

フラグの組み合わせ

GDScript
# One-shot AND deferred
trigger.body_entered.connect(_on_trigger, CONNECT_ONE_SHOT | CONNECT_DEFERRED)

8. Common Patterns

8. よく使うパターン

EventBus (Global Signal Hub)

EventBus(グローバルシグナルハブ)

The EventBus pattern uses an Autoload singleton to decouple nodes. Any node can emit or listen to global events without needing a direct reference to another node. This is one of the most powerful patterns in Godot.

EventBusパターンはAutoloadシングルトンを使ってノードを疎結合にします。どのノードも、他のノードへの直接参照なしにグローバルイベントを発火・受信できます。Godotで最も強力なパターンの一つです。

event_bus.gd (Autoload)
extends Node

# Define all global signals in one place
signal player_died
signal score_changed(new_score: int)
signal level_completed(level_id: int)
signal item_collected(item_name: String)
signal settings_changed
player.gd (emitter)
func die() -> void:
    # Any script can emit global signals
    EventBus.player_died.emit()
hud.gd (listener)
func _ready() -> void:
    # Any script can listen to global signals
    EventBus.score_changed.connect(_on_score_changed)
    EventBus.player_died.connect(_on_player_died)

func _on_score_changed(new_score: int) -> void:
    score_label.text = "Score: %d" % new_score

func _on_player_died() -> void:
    game_over_screen.show()
Setting Up Autoload
Autoloadの設定方法

Go to Project > Project Settings > Autoload, add your event_bus.gd script, and name it EventBus. It becomes a globally accessible singleton automatically.

プロジェクト > プロジェクト設定 > 自動読み込みで、event_bus.gd スクリプトを追加し、名前を EventBus にします。自動的にグローバルアクセス可能なシングルトンになります。

Signal Relay (Parent-Child Communication)

シグナルリレー(親子間通信)

A parent node listens to its children's signals and relays or aggregates information. Children never need to know about each other.

親ノードが子ノードのシグナルをリッスンし、情報をリレーまたは集約します。子ノードは互いの存在を知る必要がありません。

inventory.gd
signal inventory_updated

func _ready() -> void:
    # Connect to all slot children
    for slot in get_children():
        if slot.has_signal("item_changed"):
            slot.item_changed.connect(_on_slot_changed)

func _on_slot_changed() -> void:
    inventory_updated.emit()

Signal + Await for Sequential Game Flow

Signal + Awaitによる順次ゲームフロー

level_manager.gd
func run_level() -> void:
    spawn_enemies()
    await EventBus.all_enemies_defeated

    show_treasure_chest()
    await EventBus.chest_opened

    play_exit_animation()
    await get_tree().create_timer(1.5).timeout

    load_next_level()

Dynamic Connections for Spawned Nodes

スポーンしたノードの動的接続

enemy_spawner.gd
func spawn_enemy(pos: Vector2) -> void:
    var enemy = enemy_scene.instantiate()
    enemy.position = pos

    # Connect signals before adding to scene tree
    enemy.died.connect(_on_enemy_died.bind(enemy))
    enemy.health_changed.connect(_on_enemy_health_changed)

    add_child(enemy)

func _on_enemy_died(enemy: Node) -> void:
    enemies_alive -= 1
    enemy.queue_free()

9. Migration Cheat Sheet (Godot 3 → 4)

9. 移行チートシート(Godot 3 → 4)

Bookmark this table for quick reference when porting your Godot 3 project.

Godot 3プロジェクトの移植時のクイックリファレンスとしてこの表をブックマークしてください。

Operation操作 Godot 3 Godot 4
Connect接続 connect("sig", obj, "method") sig.connect(method)
Disconnect切断 disconnect("sig", obj, "method") sig.disconnect(method)
Emit発火 emit_signal("sig", args) sig.emit(args)
Check connection接続確認 is_connected("sig", obj, "method") sig.is_connected(method)
Wait for signalシグナル待機 yield(obj, "sig") await obj.sig
Bind extra args追加引数 connect("sig", obj, "method", [data]) sig.connect(method.bind(data))
One-shot一回限り connect("sig", obj, "method", [], CONNECT_ONESHOT) sig.connect(method, CONNECT_ONE_SHOT)

10. Common Mistakes

10. よくある間違い

1. Using String-Based Connect (Godot 3 Style)

1. 文字列ベースのconnect(Godot 3スタイル)を使う

GDScript
# WRONG — Godot 3 syntax, will not compile
button.connect("pressed", self, "_on_button_pressed")

# CORRECT — Godot 4 syntax
button.pressed.connect(_on_button_pressed)

2. Using emit_signal() Instead of .emit()

2. .emit()の代わりにemit_signal()を使う

While emit_signal() still works, it bypasses compile-time checks and is officially deprecated. Use .emit().

emit_signal() はまだ動作しますが、コンパイル時チェックをバイパスし、公式に非推奨です。.emit() を使いましょう。

GDScript
# AVOID — deprecated, no compile-time checks
emit_signal("health_changed", health)

# PREFER — type-safe, catches typos at compile time
health_changed.emit(health)

3. Connecting to a Freed Node

3. 解放されたノードへの接続

If you connect a signal to a method on a node, and that node gets queue_free()'d, the next signal emission will crash. Solutions:

ノードのメソッドにシグナルを接続し、そのノードが queue_free() で解放されると、次のシグナル発火時にクラッシュします。解決策:

  • Disconnect in _exit_tree()
  • _exit_tree() で切断する
  • Use CONNECT_ONE_SHOT for one-time events
  • 一回限りのイベントには CONNECT_ONE_SHOT を使う
  • Check is_instance_valid(target) before emitting
  • 発火前に is_instance_valid(target) で確認する
GDScript
# Safe emission pattern
for connection in my_signal.get_connections():
    if is_instance_valid(connection["callable"].get_object()):
        pass  # Connection is still valid
my_signal.emit()  # Godot handles invalid connections gracefully in 4.x

4. Forgetting to Disconnect Cross-Scene Signals

4. シーンをまたぐシグナルの切断忘れ

Connections to Autoload signals persist across scene changes. If you connect in _ready() but never disconnect, you'll get errors or unexpected behavior when the scene is reloaded.

Autoloadシグナルへの接続はシーン変更を越えて持続します。_ready() で接続して切断しなければ、シーンがリロードされたときにエラーや予期しない動作が発生します。

GDScript
# WRONG — never disconnects, leaks across scene changes
func _ready() -> void:
    EventBus.score_changed.connect(_on_score_changed)

# CORRECT — clean disconnect
func _ready() -> void:
    EventBus.score_changed.connect(_on_score_changed)

func _exit_tree() -> void:
    EventBus.score_changed.disconnect(_on_score_changed)

5. Connecting the Same Signal Twice

5. 同じシグナルを2回接続する

If _ready() is called multiple times (e.g., re-parenting a node), you may accidentally connect the same method twice. The handler will then fire twice per emission.

_ready() が複数回呼ばれる場合(ノードの再親設定など)、同じメソッドを2回接続してしまうことがあります。ハンドラーは発火ごとに2回実行されてしまいます。

GDScript
# Guard against double-connection
func _ready() -> void:
    if not EventBus.score_changed.is_connected(_on_score_changed):
        EventBus.score_changed.connect(_on_score_changed)

Want AI to Manage Your Signal Architecture?

AIにシグナル設計を任せてみませんか?

Godot MCP Pro connects AI assistants like Claude directly to your Godot editor. It can connect, disconnect, audit, and visualize signal flows across your entire project — automatically.

Godot MCP ProはClaudeなどのAIアシスタントをGodotエディタに直接接続します。プロジェクト全体のシグナルフローの接続・切断・監査・可視化を自動で行えます。

analyze_signal_flow find_signal_connections connect_signal disconnect_signal get_signals
Get Godot MCP Pro — $5Godot MCP Pro を入手 — $5