通用的做法是建立单例event_bus
,定义subscribe
订阅和publish
发布函数,就像这个插件一样,当然另一种做法,也可以把要用到的信号全部定义在event-bus里(省去了获取信号所在脚本的麻烦),然后用godot的connect等方法。相对于自己实现的subscribe
订阅和publish
发布函数,用信号连接这种有自动补全,缺点是不够灵活。
我想到的一种做法是对event_bus单例进一步特化,就能一定程度的简化掉subscribe
订阅这个步骤
把脚本A要处理的事件全部交给_event_handler
这一个函数,简化了链接方法
#Script A
export var _event:Array = ["event_a","event_b"]
func _event_handler(event:String, value):
match event: #match 相较于if性能差很多
"event_a":
#处理数据
"event_b":
#处理数据
func _get_handler_events():
return _event
event_bus通过监听场景树的node_added信号,检测哪些节点有_get_handler_events
函数,然后注册订阅事件,简化了手动event_bus.subscribe()
,而event_bus处理当有事件发送时,把事件通过注册的脚本分发一下
#event_bus
class_name TestEventBus
var events:Dictionary = {}
func _enter_tree() -> void:
#监听节点加入场景树的信号
get_tree().connect("node_added",self,"_on_node_added")
func _on_node_added(node:Node):
if node.has_method("_get_handler_events"):
var _events = node._get_handler_events() as Array
#可能存在多个节点用同一个event名,故用数组存储节点
var handlers:Array
for e in _events:
handlers = events.get(e, [])
handlers.append(node)
events[e] = handlers
func publish(event:String, value = null):
var nodes = events.get(event,[])
for n in nodes:
if is_instance_valid(n) and n.has_method("_event_handler"):
n._event_handler(event, value)