Skip to content

SignalBus API 参考

SignalBus 是 GDSignalBus 的核心类,提供高性能的信号总线功能。

获取单例

gdscript
var bus = SignalBus.get_singleton()

基础信号操作

emit()

发射信号到默认频道。

gdscript
bus.emit(signal_name: String, args: Array)

参数:

  • signal_name: 信号名称
  • args: 信号参数数组

示例:

gdscript
bus.emit("player_died", [])
bus.emit("item_collected", ["coin", 100])

emit_on_channel()

发射信号到指定频道。

gdscript
bus.emit_on_channel(channel: String, signal_name: String, args: Array)

参数:

  • channel: 频道名称
  • signal_name: 信号名称
  • args: 信号参数数组

示例:

gdscript
bus.emit_on_channel("ui", "button_clicked", ["start_button"])
bus.emit_on_channel("gameplay", "enemy_spawned", [enemy_data])

信号订阅

subscribe()

订阅信号到默认频道。

gdscript
var subscription_id = bus.subscribe(signal_name: String, callable: Callable)

参数:

  • signal_name: 信号名称
  • callable: 回调函数

返回值:

  • int64_t: 订阅ID,用于取消订阅

示例:

gdscript
var id = bus.subscribe("player_died", _on_player_died)

func _on_player_died():
    print("玩家死亡")
    restart_level()

subscribe_on_channel()

订阅信号到指定频道。

gdscript
var subscription_id = bus.subscribe_on_channel(channel: String, signal_name: String, callable: Callable)

参数:

  • channel: 频道名称
  • signal_name: 信号名称
  • callable: 回调函数

返回值:

  • int64_t: 订阅ID

示例:

gdscript
var id = bus.subscribe_on_channel("ui", "button_clicked", _on_button_clicked)

func _on_button_clicked(button_name):
    print("按钮被点击: ", button_name)

取消订阅

unsubscribe()

通过订阅ID取消订阅。

gdscript
var success = bus.unsubscribe(subscription_id: int64_t)

参数:

  • subscription_id: 订阅ID

返回值:

  • bool: 是否成功取消订阅

unsubscribe_all()

取消指定对象的所有订阅。

gdscript
bus.unsubscribe_all(subscriber: Object)

参数:

  • subscriber: 订阅者对象

示例:

gdscript
func _exit_tree():
    bus.unsubscribe_all(self)

实例级信号

get_instance_signal()

获取对象的实例信号名称。

gdscript
var instance_signal = bus.get_instance_signal(object: Object, base_signal: String)

参数:

  • object: 对象实例
  • base_signal: 基础信号名称

返回值:

  • String: 实例信号名称

subscribe_instance()

订阅实例级信号。

gdscript
var subscription_id = bus.subscribe_instance(object: Object, base_signal: String, callable: Callable)

参数:

  • object: 对象实例
  • base_signal: 基础信号名称
  • callable: 回调函数

返回值:

  • int64_t: 订阅ID

emit_instance()

发射实例级信号。

gdscript
bus.emit_instance(object: Object, base_signal: String, args: Array)

参数:

  • object: 对象实例
  • base_signal: 基础信号名称
  • args: 信号参数数组

示例:

gdscript
# 为不同玩家实例创建独立信号
var player1 = Player.new()
var player2 = Player.new()

bus.subscribe_instance(player1, "health_changed", _on_player1_health)
bus.subscribe_instance(player2, "health_changed", _on_player2_health)

bus.emit_instance(player1, "health_changed", [80])
bus.emit_instance(player2, "health_changed", [60])

信号过滤

subscribe_filtered()

订阅带过滤器的信号。

gdscript
var subscription_id = bus.subscribe_filtered(signal_name: String, filter: Callable, callable: Callable)

参数:

  • signal_name: 信号名称
  • filter: 过滤器函数,返回 true 时触发回调
  • callable: 回调函数

返回值:

  • int64_t: 订阅ID

subscribe_filtered_on_channel()

在指定频道订阅带过滤器的信号。

gdscript
var subscription_id = bus.subscribe_filtered_on_channel(channel: String, signal_name: String, filter: Callable, callable: Callable)

参数:

  • channel: 频道名称
  • signal_name: 信号名称
  • filter: 过滤器函数
  • callable: 回调函数

返回值:

  • int64_t: 订阅ID

示例:

gdscript
# 只接收价值大于10的物品
bus.subscribe_filtered("item_collected", 
    func(value): return value > 10,
    _on_valuable_item
)

func _on_valuable_item(value):
    print("获得贵重物品,价值: ", value)

异步信号

subscribe_async()

订阅异步信号。

gdscript
var subscription_id = bus.subscribe_async(signal_name: String, callback: Callable)

参数:

  • signal_name: 信号名称
  • callback: 异步回调函数

返回值:

  • int64_t: 订阅ID

subscribe_async_with_callbacks()

订阅异步信号,带完成和错误回调。

gdscript
var subscription_id = bus.subscribe_async_with_callbacks(signal_name: String, callback: Callable, on_complete: Callable, on_error: Callable)

参数:

  • signal_name: 信号名称
  • callback: 异步回调函数
  • on_complete: 完成回调函数
  • on_error: 错误回调函数

返回值:

  • int64_t: 订阅ID

emit_async()

发射异步信号。

gdscript
var task_ids = bus.emit_async(signal_name: String, args: Array)

参数:

  • signal_name: 信号名称
  • args: 信号参数数组

返回值:

  • Array: 任务ID数组

cancel_async_task()

取消异步任务。

gdscript
var success = bus.cancel_async_task(task_id: int64_t)

参数:

  • task_id: 任务ID

返回值:

  • bool: 是否成功取消

wait_all_async_tasks()

等待所有异步任务完成。

gdscript
bus.wait_all_async_tasks()

get_active_async_task_count()

获取活动异步任务数量。

gdscript
var count = bus.get_active_async_task_count()

返回值:

  • int32_t: 活动任务数量

process_async_tasks()

处理已完成的异步任务(需要在主线程定期调用)。

gdscript
bus.process_async_tasks()

示例:

gdscript
func _process(_delta):
    bus.process_async_tasks()

func _ready():
    bus.subscribe_async("heavy_computation", func(data):
        # 在后台线程执行耗时操作
        OS.delay_msec(2000)
        return data * 2
    )
    
    bus.subscribe_async_with_callbacks("file_operation",
        func(path): return FileAccess.open(path, FileAccess.READ).get_as_text(),
        func(content): print("文件读取完成: ", content.length()),
        func(error): print("文件读取失败: ", error)
    )

原生信号桥接

bridge_signal()

将节点信号桥接到默认频道。

gdscript
var bridge_id = bus.bridge_signal(node: Node, signal_name: String)

参数:

  • node: 节点对象
  • signal_name: 节点信号名称

返回值:

  • int64_t: 桥接ID

bridge_signal_to_channel()

将节点信号桥接到指定频道。

gdscript
var bridge_id = bus.bridge_signal_to_channel(node: Node, signal_name: String, channel: String)

参数:

  • node: 节点对象
  • signal_name: 节点信号名称
  • channel: 目标频道

返回值:

  • int64_t: 桥接ID

relay_node_signal()

将节点信号转发为不同的总线信号。

gdscript
var bridge_id = bus.relay_node_signal(node: Node, node_signal: String, bus_signal: String)

参数:

  • node: 节点对象
  • node_signal: 节点信号名称
  • bus_signal: 总线信号名称

返回值:

  • int64_t: 桥接ID

relay_node_signal_to_channel()

将节点信号转发到指定频道的不同总线信号。

gdscript
var bridge_id = bus.relay_node_signal_to_channel(node: Node, node_signal: String, bus_signal: String, channel: String)

参数:

  • node: 节点对象
  • node_signal: 节点信号名称
  • bus_signal: 总线信号名称
  • channel: 目标频道

返回值:

  • int64_t: 桥接ID

unbridge_signal()

移除信号桥接。

gdscript
var success = bus.unbridge_signal(bridge_id: int64_t)

参数:

  • bridge_id: 桥接ID

返回值:

  • bool: 是否成功移除

cleanup_invalid_bridges()

清理无效的桥接。

gdscript
var cleaned_count = bus.cleanup_invalid_bridges()

返回值:

  • int32_t: 清理的桥接数量

示例:

gdscript
func _ready():
    # 桥接按钮信号
    var bridge_id1 = bus.bridge_signal($StartButton, "pressed")
    var bridge_id2 = bus.relay_node_signal($SettingsButton, "pressed", "settings_opened")
    
    # 订阅桥接后的信号
    bus.subscribe("pressed", _on_any_button_pressed)
    bus.subscribe("settings_opened", _on_settings_opened)

func _on_any_button_pressed():
    print("某个按钮被按下")

func _on_settings_opened():
    print("设置界面打开")

func _exit_tree():
    # 清理桥接
    bus.unbridge_signal(bridge_id1)
    bus.unbridge_signal(bridge_id2)

调试和监控

set_debug_enabled()

启用或禁用调试模式。

gdscript
bus.set_debug_enabled(enabled: bool)

get_signal_list()

获取所有信号列表。

gdscript
var signals = bus.get_signal_list()

返回值:

  • Array: 信号信息数组

get_channel_list()

获取所有频道列表。

gdscript
var channels = bus.get_channel_list()

返回值:

  • PackedStringArray: 频道名称数组

get_subscriber_count()

获取信号的订阅者数量(所有频道)。

gdscript
var count = bus.get_subscriber_count(signal_name: String)

返回值:

  • int32_t: 订阅者数量

get_subscriber_count_on_channel()

获取特定频道信号的订阅者数量。

gdscript
var count = bus.get_subscriber_count_on_channel(channel: String, signal_name: String)

返回值:

  • int32_t: 订阅者数量

get_total_signals_emitted()

获取已发射信号总数。

gdscript
var total = bus.get_total_signals_emitted()

返回值:

  • int64_t: 信号总数

清理操作

clear_channel()

清空指定频道的所有订阅。

gdscript
bus.clear_channel(channel: String)

clear_all()

清空所有频道和订阅。

gdscript
bus.clear_all()

使用示例

基础用法

gdscript
extends Node

@onready var bus = SignalBus.get_singleton()

func _ready():
    # 订阅信号
    bus.subscribe("player_died", _on_player_died)
    bus.subscribe_on_channel("ui", "button_clicked", _on_button_clicked)
    
    # 发射信号
    bus.emit("player_died", [])
    bus.emit_on_channel("ui", "button_clicked", ["start_button"])

func _on_player_died():
    print("玩家死亡,重新开始")
    get_tree().reload_current_scene()

func _on_button_clicked(button_name):
    print("按钮点击: ", button_name)

异步处理

gdscript
func _ready():
    # 异步订阅
    bus.subscribe_async("heavy_task", func(data):
        OS.delay_msec(3000)  # 模拟耗时操作
        return data * 2
    )
    
    bus.subscribe_async_with_callbacks("file_load",
        func(path): return FileAccess.open(path, FileAccess.READ).get_as_text(),
        func(content): print("文件加载成功"),
        func(error): print("文件加载失败")
    )

func _process(_delta):
    bus.process_async_tasks()  # 必须在主线程调用

func _input(event):
    if event.is_action_pressed("ui_accept"):
        bus.emit_async("heavy_task", [42])
    if event.is_action_pressed("ui_cancel"):
        bus.emit_async("file_load", ["user://save.dat"])

通过这些 API,你可以构建高性能、解耦的游戏事件系统。

基于 MIT 许可发布