1. Giriş — Godot 4'te Neler Değişti
Godot 4, signal'lerin çalışma şeklini tamamen elden geçirdi. Godot 3'ten geliyorsanız: eski string tabanlı object.connect("signal_name", target, "method_name") sözdizimi artık yok. Onun yerine Godot 4, tip güvenli, yeniden düzenlemeye (refactoring) uygun ve hataları çalışma zamanı yerine derleme zamanında yakalayan Callable tabanlı bir API kullanır.
Bu rehber, Godot 4.4+ içinde signal'ler hakkında bilmeniz gereken her şeyi kapsar: tanımlama, bağlama, bağlantı kesme, gönderme, bekleme (await) ve pratikte en kullanışlı kalıplar.
Godot 4'te signal'ler birinci sınıf nesnelerdir. Onlara özellik olarak erişirsiniz (örn. button.pressed) ve üzerlerinde metot çağırırsınız (.connect(), .emit(), .disconnect()). Artık string tabanlı API yok.
2. Özel Signal'ler Tanımlama
Signal'leri betiğinizin başında signal anahtar sözcüğüyle tanımlayın. İsteğe bağlı olarak, dokümantasyon ve editör otomatik tamamlama için parametre adları ve tipleri belirtebilirsiniz.
# 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)
Signal parametrelerine her zaman tip bilgisi ekleyin. Bu, editörde otomatik tamamlamayı etkinleştirir ve kodunuzu kendi kendini belgeler hale getirir. Tip bilgisi olan signal'ler ayrıca Node dock'unun Signals sekmesinde parametre bilgisini gösterir.
3. Signal'leri Bağlama (Yeni Yöntem)
Godot 4'teki en büyük değişiklik, signal'leri nasıl bağladığınızdır. String'ler geçmek yerine, signal'i bir özellik olarak kullanır ve .connect() metodunu bir Callable (bir fonksiyona referans) ile çağırırsınız.
Temel Bağlantı
# 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!")
bind() ile Ek Argümanlı Bağlantı
.bind() kullanarak signal ile birlikte ek veri geçirebilirsiniz. Bu, birden fazla signal'i aynı metoda bağlarken kullanışlıdır.
# 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 (Satır İçi) Bağlantılar
Kısa işleyiciler için doğrudan bir lambda fonksiyonu kullanabilirsiniz. Böylece basit mantık, bağlantı noktasına yakın kalır.
# 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!")
)
Lambda bağlantıları kolayca kesilemez, çünkü anonim fonksiyona bir referansınız yoktur. Daha sonra bağlantıyı kesmeniz gerekiyorsa, Callable'ı bir değişkende saklayın veya bunun yerine adlandırılmış bir metot kullanın.
Editörde Bağlama (Node Dock)
Signal'leri Godot editör arayüzü üzerinden de bağlayabilirsiniz. Bir node seçin, Node dock > Signals sekmesini açın, bir signal'e çift tıklayın ve hedef node ile metodu seçin. Editör, betiğinizde _on_button_pressed() gibi bir metodu otomatik olarak oluşturur. Bu, kodda .connect() çağırmakla aynıdır — sadece yazma zahmetinden kurtarır.
4. Signal Bağlantısını Kesme
Bir signal'i artık almak istemediğinizde bağlantısını kesin. Bu, node'lar serbest bırakıldığında veya oyun durumları değiştirildiğinde hataları önlemek için önemlidir.
# 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)
Sahneler arası signal bağlantıları için (örn. bir Autoload'a bağlanma), node serbest bırakıldığında sarkan referansları önlemek amacıyla her zaman _exit_tree() içinde bağlantıyı kesin:
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. Signal Gönderme
Godot 4'te, eski emit_signal() yerine .emit() kullanın. Signal bir nesnedir, bu yüzden metodu doğrudan onun üzerinde çağırırsınız.
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
Eski emit_signal("signal_name") Godot 4'te teknik olarak hâlâ çalışır ancak kullanımdan kaldırılmıştır. Yeni kod için her zaman signal_name.emit() tercih edin. String tabanlı sürüm, gelecekteki bir Godot sürümünde kaldırılabilir.
6. Signal'leri Bekleme (await)
Godot 4, yield() yerine await getirdi. Bu, bir signal tetiklenene kadar bir fonksiyonu duraklatmanıza olanak tanır — ara sahneler, öğreticiler, sıralı animasyonlar ve zamanlanmış olaylar için mükemmeldir.
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!")
Beklenen Signal'lerden Değer Almak
Signal argümanlar gönderiyorsa, await bunları döndürür. Tek argüman için değeri doğrudan alırsınız. Birden fazla argüman için bir dizi (array) alırsınız.
# 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 Bağlantı Bayrakları
Godot, bağlantının davranışını değiştiren bağlantı bayraklarını .connect() metodunun ikinci argümanı olarak sağlar.
CONNECT_ONE_SHOT
Signal bir kez tetiklendikten sonra bağlantı otomatik olarak kaldırılır. Ölüm animasyonları veya başarım açma gibi tek seferlik olaylar için mükemmeldir.
# 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
Bağlı metot, hemen değil, geçerli karenin sonunda (boşta kalma süresi içinde) çağrılır. Signal işleyicisi sahne ağacını (scene tree) değiştirdiğinde kullanışlıdır; çünkü fizik veya signal işleme sırasında bunu yapmak güvenli değildir.
# 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()
Bayrakları Birleştirme
# One-shot AND deferred
trigger.body_entered.connect(_on_trigger, CONNECT_ONE_SHOT | CONNECT_DEFERRED)
8. Sık Kullanılan Kalıplar
EventBus (Global Signal Merkezi)
EventBus kalıbı, node'ları birbirinden ayırmak için bir Autoload singleton kullanır. Herhangi bir node, başka bir node'a doğrudan referansa ihtiyaç duymadan global olayları gönderebilir veya dinleyebilir. Bu, Godot'taki en güçlü kalıplardan biridir.
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
func die() -> void:
# Any script can emit global signals
EventBus.player_died.emit()
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()
Project > Project Settings > Autoload yolunu izleyin, event_bus.gd betiğinizi ekleyin ve adını EventBus koyun. Otomatik olarak global erişilebilir bir singleton haline gelir.
Signal Aktarımı (Ebeveyn-Çocuk İletişimi)
Bir ebeveyn node, çocuklarının signal'lerini dinler ve bilgiyi aktarır veya toplar. Çocukların birbirini bilmesine hiç gerek yoktur.
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()
Sıralı Oyun Akışı için Signal + Await
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()
Oluşturulan Node'lar için Dinamik Bağlantılar
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. Geçiş Kılavuzu (Godot 3 → 4)
Godot 3 projenizi taşırken hızlı başvuru için bu tabloyu yer imlerinize ekleyin.
| İşlem | Godot 3 | Godot 4 |
|---|---|---|
| Bağlama | connect("sig", obj, "method") |
sig.connect(method) |
| Bağlantı kesme | disconnect("sig", obj, "method") |
sig.disconnect(method) |
| Gönderme | emit_signal("sig", args) |
sig.emit(args) |
| Bağlantı kontrolü | is_connected("sig", obj, "method") |
sig.is_connected(method) |
| Signal bekleme | yield(obj, "sig") |
await obj.sig |
| Ek argüman bağlama | connect("sig", obj, "method", [data]) |
sig.connect(method.bind(data)) |
| Tek seferlik | connect("sig", obj, "method", [], CONNECT_ONESHOT) |
sig.connect(method, CONNECT_ONE_SHOT) |
10. Sık Yapılan Hatalar
1. String Tabanlı connect Kullanmak (Godot 3 Stili)
# 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. .emit() Yerine emit_signal() Kullanmak
emit_signal() hâlâ çalışsa da, derleme zamanı denetimlerini atlar ve resmî olarak kullanımdan kaldırılmıştır. .emit() kullanın.
# AVOID — deprecated, no compile-time checks
emit_signal("health_changed", health)
# PREFER — type-safe, catches typos at compile time
health_changed.emit(health)
3. Serbest Bırakılmış Bir Node'a Bağlanmak
Bir signal'i bir node üzerindeki metoda bağlarsanız ve o node queue_free() ile serbest bırakılırsa, sonraki signal gönderimi çökmeye neden olur. Çözümler:
_exit_tree()içinde bağlantıyı kesin- Tek seferlik olaylar için
CONNECT_ONE_SHOTkullanın - Göndermeden önce
is_instance_valid(target)ile kontrol edin
# 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. Sahneler Arası Signal'lerin Bağlantısını Kesmeyi Unutmak
Autoload signal'lerine yapılan bağlantılar sahne değişiklikleri boyunca kalıcı olur. _ready() içinde bağlanıp hiç bağlantıyı kesmezseniz, sahne yeniden yüklendiğinde hatalar veya beklenmedik davranışlar alırsınız.
# 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. Aynı Signal'i İki Kez Bağlamak
_ready() birden fazla kez çağrılırsa (örn. bir node'un ebeveynini değiştirme), aynı metodu yanlışlıkla iki kez bağlayabilirsiniz. Bu durumda işleyici her gönderimde iki kez tetiklenir.
# Guard against double-connection
func _ready() -> void:
if not EventBus.score_changed.is_connected(_on_score_changed):
EventBus.score_changed.connect(_on_score_changed)
Signal Mimarinizi Yapay Zeka Yönetsin İster misiniz?
Godot MCP Pro, Claude gibi yapay zeka asistanlarını doğrudan Godot editörünüze bağlar. Projenizin tamamındaki signal akışlarını otomatik olarak bağlayabilir, kesebilir, denetleyebilir ve görselleştirebilir.
analyze_signal_flow
find_signal_connections
connect_signal
disconnect_signal
get_signals