You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在GDScript中编写静态事件发射器?连接问题求助

Godot实现静态事件发射器的问题与解决办法

Godot本身不支持静态信号,我尝试了两种实现静态事件发射器的方案,但连接时都遇到了问题:

尝试过的方案及问题

  • 方案1:静态原生Signal变量
    直接声明静态Signal,运行时连接会出现被忽略的错误:

    static var my_signal: Signal = Signal()
    
  • 方案2:自定义StaticSignal类型
    嵌套在主类里定义了自定义信号类,但连接时提示“.connect成员未找到”:

    static var my_signal: StaticSignal = StaticSignal.new()
    
    class_name StaticSignal
    
    var _callables: Dictionary
    
    func connect(callable: Callable) -> void:
        self._callables[callable] = true
    
    func disconnect(callable: Callable) -> void:
        self._callables.erase(callable)
    
    func emit(data: Variant) -> void:
        for callable in self._callables:
            callable(data)
    

我的连接代码如下:

static func _static_init():
    ChatLog.new_message.connect(func(msg):
        if len(_log) >= LIMIT:
            _log.remove_at(0)
        _log.append(msg))

问题原因与修复方法

自定义StaticSignal的错误修复

报错的核心原因是静态初始化时机不对:_static_init在类加载时就执行,此时嵌套的StaticSignal类还没完成注册,Godot识别不了它的方法。

解决办法:

  1. 把StaticSignal单独放到一个独立脚本文件(比如StaticSignal.gd),确保类在主脚本加载前完成注册;
  2. 不要在_static_init里连接信号,改成在首次使用时初始化连接,避免时机问题。

修改后的独立StaticSignal.gd:

class_name StaticSignal

var _callables: Dictionary = {}

func _init() -> void:
    _callables = {}

func connect(callable: Callable) -> void:
    if callable.is_valid():
        _callables[callable] = true

func disconnect(callable: Callable) -> void:
    _callables.erase(callable)

func emit(data: Variant = null) -> void:
    # 遍历键的副本,防止遍历中修改字典出错
    for callable in _callables.keys():
        if callable.is_valid():
            callable.callv([data])

主类的使用示例:

class_name ChatLog

static var new_message: StaticSignal = StaticSignal.new()
static var _log: Array = []
const LIMIT: int = 10

# 替代_static_init,首次使用时初始化连接
static func init_log() -> void:
    if new_message._callables.empty():
        new_message.connect(func(msg):
            if _log.size() >= LIMIT:
                _log.remove_at(0)
            _log.append(msg))

原生Signal静态变量的问题说明

原生Signal是绑定到Object实例设计的,静态环境下没有对应的对象信号系统支撑,所以这种方案本身就不可行,直接放弃,用自定义静态信号类更靠谱。

额外优化建议

  • 连接时检查Callable有效性,避免无效调用;
  • 发射信号时遍历字典键的副本,防止遍历中修改字典(比如断开连接)引发异常;
  • 支持无参数的emit调用,提升灵活性。

内容的提问来源于stack exchange,提问作者Hydroper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:39:57