1. परिचय — Godot 4 में क्या बदला
Godot 4 ने signals के काम करने के तरीके को पूरी तरह से नया रूप दिया है। अगर आप Godot 3 से आ रहे हैं, तो पुरानी string-आधारित सिंटैक्स object.connect("signal_name", target, "method_name") अब मौजूद नहीं है। इसकी जगह Godot 4 एक callable-आधारित API का उपयोग करता है जो type-safe और refactoring-अनुकूल है और errors को runtime के बजाय compile time पर पकड़ लेता है।
यह गाइड वह सब कुछ कवर करती है जो आपको Godot 4.4+ में signals के बारे में जानना चाहिए: घोषित करना, connect करना, disconnect करना, emit करना, await करना और वास्तविक दुनिया के सबसे उपयोगी patterns।
Godot 4 में signals first-class objects हैं। आप इन्हें properties के रूप में एक्सेस करते हैं (जैसे, button.pressed) और इन पर methods कॉल करते हैं (.connect(), .emit(), .disconnect())। अब कोई string-आधारित API नहीं।
2. कस्टम signals घोषित करना
अपनी स्क्रिप्ट के शीर्ष पर signal कीवर्ड के साथ signals घोषित करें। आप वैकल्पिक रूप से documentation और editor autocomplete के लिए parameter नाम और types निर्दिष्ट कर सकते हैं।
# 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 parameters में हमेशा type hints जोड़ें। इससे editor में autocomplete सक्रिय होता है और आपका कोड स्वयं-दस्तावेज़ीकृत बनता है। type hints वाले signals, Node dock के Signals tab में parameter जानकारी भी दिखाते हैं।
3. Signals को connect करना (नया तरीका)
Godot 4 में सबसे बड़ा बदलाव यह है कि आप signals को कैसे connect करते हैं। strings पास करने के बजाय, आप signal को एक property के रूप में उपयोग करते हैं और .connect() को एक Callable (किसी function का reference) के साथ कॉल करते हैं।
बुनियादी connection
# 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() के माध्यम से अतिरिक्त arguments के साथ connection
signal के साथ अतिरिक्त data पास करने के लिए .bind() का उपयोग करें। यह तब उपयोगी है जब आप कई signals को एक ही method से connect करते हैं।
# 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
छोटे handlers के लिए, आप सीधे एक lambda function का उपयोग कर सकते हैं। इससे सरल logic connection बिंदु के पास रहती है।
# 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 connections को आसानी से disconnect नहीं किया जा सकता क्योंकि आपके पास anonymous function का reference नहीं होता। अगर आपको बाद में disconnect करना है, तो Callable को एक variable में स्टोर करें या इसके बजाय named method का उपयोग करें।
Editor में connect करना (Node dock)
आप अभी भी Godot editor UI के माध्यम से signals connect कर सकते हैं। एक node चुनें, Node dock > Signals tab खोलें, किसी signal पर डबल-क्लिक करें, और target node तथा method चुनें। editor आपकी स्क्रिप्ट में स्वतः _on_button_pressed() जैसी method बना देगा। यह कोड में .connect() कॉल करने के समान ही है — बस टाइपिंग बचती है।
4. Signals को disconnect करना
जब आप किसी signal को प्राप्त नहीं करना चाहते तो उसे disconnect करें। यह nodes के free होने या game states बदलने पर errors से बचने के लिए महत्वपूर्ण है।
# 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)
scene-पार signal connections (जैसे किसी Autoload से connect करना) के लिए, node के free होने पर dangling references रोकने के लिए हमेशा _exit_tree() में disconnect करें:
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. Signals को emit करना
Godot 4 में, पुराने emit_signal() के बजाय .emit() का उपयोग करें। signal एक object है, इसलिए आप method को सीधे उस पर कॉल करते हैं।
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
पुराना emit_signal("signal_name") Godot 4 में तकनीकी रूप से अभी भी काम करता है लेकिन deprecated है। नए कोड के लिए हमेशा signal_name.emit() को प्राथमिकता दें। string-आधारित संस्करण भविष्य के किसी Godot रिलीज़ में हटाया जा सकता है।
6. Signals का await करना
Godot 4 ने yield() की जगह await ले लिया है। इससे आप किसी function को तब तक रोक सकते हैं जब तक कोई signal fire न हो — जो cutscenes, tutorials, अनुक्रमिक animations और timed events के लिए एकदम सही है।
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!")
await किए गए signals से values प्राप्त करना
अगर signal arguments emit करता है, तो await उन्हें लौटाता है। एक single argument के लिए, आपको value सीधे मिलती है। कई arguments के लिए, आपको एक array मिलता है।
# 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
Godot .connect() के दूसरे argument के रूप में connection flags प्रदान करता है, जिनसे आप connection के व्यवहार को समायोजित कर सकते हैं।
CONNECT_ONE_SHOT
signal के एक बार fire होने के बाद connection स्वतः हटा दिया जाता है। death animations या achievement unlocks जैसी एकबारगी events के लिए एकदम सही।
# 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
connected method तुरंत के बजाय वर्तमान frame के अंत में (idle समय के दौरान) कॉल की जाती है। यह तब उपयोगी है जब signal handler scene tree को बदलता है, जो physics या signal processing के दौरान सुरक्षित नहीं होता।
# 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()
Flags को जोड़ना
# One-shot AND deferred
trigger.body_entered.connect(_on_trigger, CONNECT_ONE_SHOT | CONNECT_DEFERRED)
8. आम patterns
EventBus (ग्लोबल signal hub)
EventBus pattern nodes को decouple करने के लिए एक Autoload singleton का उपयोग करता है। कोई भी node दूसरे node के सीधे reference की आवश्यकता के बिना global events emit या सुन सकता है। यह Godot में सबसे शक्तिशाली patterns में से एक है।
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 पर जाएँ, अपनी event_bus.gd स्क्रिप्ट जोड़ें और उसे EventBus नाम दें। यह स्वतः एक globally accessible singleton बन जाता है।
Signal relay (parent-child संचार)
एक parent node अपने children के signals को सुनता है और जानकारी को relay या aggregate करता है। children को कभी एक-दूसरे के बारे में जानने की जरूरत नहीं होती।
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()
अनुक्रमिक game flow के लिए 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()
spawn किए गए nodes के लिए डायनामिक connections
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. माइग्रेशन चीट शीट (Godot 3 → 4)
अपने Godot 3 प्रोजेक्ट को पोर्ट करते समय त्वरित संदर्भ के लिए इस तालिका को बुकमार्क करें।
| ऑपरेशन | 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) |
| Connection जाँचना | is_connected("sig", obj, "method") |
sig.is_connected(method) |
| Signal का इंतजार करना | yield(obj, "sig") |
await obj.sig |
| अतिरिक्त args bind करना | 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. आम गलतियाँ
1. String-आधारित connect (Godot 3 शैली) का उपयोग करना
# 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() के बजाय emit_signal() का उपयोग करना
हालाँकि emit_signal() अभी भी काम करता है, यह compile-time जाँचों को दरकिनार करता है और आधिकारिक रूप से deprecated है। .emit() का उपयोग करें।
# AVOID — deprecated, no compile-time checks
emit_signal("health_changed", health)
# PREFER — type-safe, catches typos at compile time
health_changed.emit(health)
3. किसी free किए गए node से connect करना
अगर आप किसी signal को किसी node की method से connect करते हैं, और वह node queue_free() हो जाता है, तो अगली signal emission crash हो जाएगी। समाधान:
_exit_tree()में disconnect करें- एकबारगी events के लिए
CONNECT_ONE_SHOTका उपयोग करें - emit करने से पहले
is_instance_valid(target)से जाँचें
# 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. scene-पार signals को disconnect करना भूल जाना
Autoload signals से connections scene बदलावों के आर-पार बने रहते हैं। अगर आप _ready() में connect करते हैं लेकिन कभी disconnect नहीं करते, तो scene के reload होने पर आपको errors या अप्रत्याशित व्यवहार मिलेगा।
# 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. एक ही signal को दो बार connect करना
अगर _ready() कई बार कॉल होता है (जैसे किसी node को re-parent करना), तो आप गलती से एक ही method को दो बार connect कर सकते हैं। तब handler प्रति emission दो बार fire होगा।
# Guard against double-connection
func _ready() -> void:
if not EventBus.score_changed.is_connected(_on_score_changed):
EventBus.score_changed.connect(_on_score_changed)
क्या आप चाहते हैं कि AI आपके signal architecture को संभाले?
Godot MCP Pro, Claude जैसे AI assistants को सीधे आपके Godot editor से जोड़ता है। यह आपके पूरे प्रोजेक्ट में signal flows को connect, disconnect, audit और visualize कर सकता है — स्वचालित रूप से।
analyze_signal_flow
find_signal_connections
connect_signal
disconnect_signal
get_signals