信号系统
信号系统
信号是 Godot 中实现松耦合事件处理的核心机制。
什么是信号
信号是一种观察者模式,允许节点在特定事件发生时通知其他对象。
内置信号
许多节点都有内置信号,可以直接连接。
# Button 节点
button.pressed.connect(_on_button_pressed)
button.toggled.connect(_on_button_toggled)
# Timer 节点
timer.timeout.connect(_on_timer_timeout)
# Area2D 节点
area2D.body_entered.connect(_on_body_entered)
area2D.body_exited.connect(_on_body_exited)
# AnimationPlayer
animation_player.animation_finished.connect(_on_animation_finished)
# 纹理按钮
texture_button.button_down.connect(_on_button_down)
texture_button.button_up.connect(_on_button_up)
自定义信号
定义信号
extends Node
# 定义信号
signal health_changed(new_value: int)
signal died()
signal item_collected(item_name: String, value: int)
发射信号
# 发射不带参数的信号
died.emit()
# 发射带参数的信号
health_changed.emit(50)
item_collected.emit("Coin", 10)
连接信号
# 在代码中连接
func _ready() -> void:
health_changed.connect(_on_health_changed)
died.connect(_game_over)
信号回调函数
func _on_health_changed(new_value: int) -> void:
update_health_bar(new_value)
func _game_over() -> void:
show_game_over_screen()
在编辑器中连接信号
- 选择节点
- 在右侧面板找到 "Node" 标签
- 双击想要连接的信号
- 选择接收信号的对象
- 选择回调函数
断开信号
# 断开特定连接
signal_name.disconnect(callback_function)
# 断开所有连接(需要手动管理)
信号参数
# 多个参数
signal player_data(name: String, level: int, exp: int)
player_data.emit("Hero", 5, 1000)
信号传递
向父节点发送信号
# 子节点
signal request_action()
# 连接父节点方法
func _ready() -> void:
request_action.connect(get_parent()._handle_action)
跨场景通信
# 使用全局单例或信号总线
# Global.gd
extends Node
signal player_died()
signal level_completed(level: int)
# 任何节点都可以访问
Global.player_died.connect(show_game_over)
信号最佳实践
- 使用有意义的名称:
health_changed比changed更清晰 - 参数类型明确:在信号定义中指定参数类型
- 及时断开:不再需要时断开信号连接,避免内存泄漏
- 单一职责:每个信号处理一件事情
常用场景示例
extends Area2D
signal coin_collected(value: int)
func _on_body_entered(body: Node2D) -> void:
if body.is_in_group("player"):
coin_collected.emit(10)
queue_free()
extends CharacterBody2D
signal health_changed(current: int, max_health: int)
signal died
var health: int = 100
var max_health: int = 100
func take_damage(amount: int) -> void:
health -= amount
health_changed.emit(health, max_health)
if health <= 0:
died.emit()
queue_free()
Callable 对象(Godot 4)
# 使用 Callable 对象
var callable = Callable(self, "_on_timeout")
timer.timeout.connect(callable)