mcpField
G
godot-signal-architecture

godot-signal-architecture

github.com/thedivergentai开发907518 次安装2 周前更新
代码仓库

关于 godot-signal-architecture

面向 Godot 开发者的信号架构技能指南,说明如何在节点层级、跨场景系统和异步流程中组织事件。它强调类型化连接、信号向上通知与方法向下调用,并提供连接清理和调试模式。

主要功能

  1. 01信号向上、方法向下的组织方式
  2. 02类型化信号与 Callable 绑定
  3. 03全局事件总线路由
  4. 04异步信号序列
  5. 05动态连接清理与信号调试

适用场景

  1. 01让子节点向父节点报告状态变化
  2. 02在跨场景系统间传递事件
  3. 03编排加载、淡出和生成等异步步骤
  4. 04切换跟踪目标并诊断遗留连接

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/thedivergentai/game-dev-agentic-skills --skill godot-signal-architecture

安装后在 Claude Code 中输入/godot-signal-architecture确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
implementation-patterns.md
migration-notes.md
scripts/
await_signal_sequencing.gd
callable_bind_context.gd
complex_signal_sequencer.gd
disconnect_ghost_signals.gd
global_event_bus.gd
global_signal_bus_router.gd
one_shot_deferred_connections.gd
safe_dynamic_connections.gd
signal_debugger.gd
signal_spy.gd
signal_up_call_down_pattern.gd
track_signal_emitter_source.gd
unbind_unwanted_args.gd

详细介绍

信号架构中绝对不要做的事

  • 绝对不要使用基于字符串的旧版 Object.connect() — 拼写错误会导致静默失败。始终使用 signal.connect(_callback) 进行编译时验证。
  • 绝对不要使用信号自上而下地指挥行为 — 信号表示过去发生的事件(例如“死亡”)。命令应使用直接方法调用(例如“击杀”)。
  • 绝对不要将同一个信号重复连接到同一个 Callable — 这会在运行时抛出 ERR_INVALID_PARAMETER,除非使用 Object.CONNECT_REFERENCE_COUNTED 标志来叠加连接。
  • 绝对不要将全局信号总线用于本地数据 — 这会污染全局状态,让调试更加困难。场景专属逻辑应使用本地连接。
  • 绝对不要假设回调必须接收信号的所有参数 — 使用 unbind() 丢弃不需要的参数,让 API 保持简洁。
  • 绝对不要创建循环信号依赖 — A 向 B 发送信号,B 又向 A 发回信号?使用中介(父节点或 AutoLoad)来打破循环。
  • 绝对不要跳过信号类型标注 — 不带类型的 signal moved 缺少编辑器支持。始终使用 signal moved(dir: Vector2)。
  • 绝对不要忘记断开动态信号 — 残留连接会导致“对空实例调用”错误。在 _exit_tree() 中断开连接,或在重新指定目标时断开连接(disconnect_ghost_signals.gd)。
  • 绝对不要发送会立即对发射者产生副作用的信号 — 如果 died.emit() 调用 queue_free(),监听器可能无法响应。先发送信号。
  • 绝对不要将信号用于高频数据流 — 每秒发送 1000 个以上的信号(例如逐粒子更新)效率很低。应使用共享数组或直接缓冲区。

向上发信号 / 向下调用

  • 子节点 → 父节点: 过去时信号(health_changed、died)。
  • 父节点 → 子节点: 直接调用 / 属性(apply_damage、play_anim)。
  • 兄弟节点: 使用父节点中介或作用域明确的 Autoload 总线 — 绝不要直接硬引用兄弟节点。

使用信号的场景: UI 按下、死亡 → 游戏结束、战利品 → 背包、跨场景总线事件。 使用直接调用的场景: 父节点指挥子节点、本地属性访问。

决策树:在哪里连接

作用域模式必需脚本
子节点通知父节点 / UI在父节点 _ready 中进行本地 signal.connectsignal_up_call_down_pattern.gd
父节点协调子节点向下调用方法(而不是信号)同上
跨场景 / 系统(成就、存档)Autoload 总线global_signal_bus_router.gd / global_event_bus.gd
线性异步步骤(加载 → 淡出 → 生成)await 信号序列await_signal_sequencing.gd / complex_signal_sequencer.gd
重新指定跟踪目标(新敌人)先断开旧连接disconnect_ghost_signals.gd
单次 / 物理安全CONNECT_ONE_SHOT / CONNECT_DEFERREDone_shot_deferred_connections.gd
附加上下文 / 丢弃参数Callable.bind / unbindcallable_bind_context.gd / unbind_unwanted_args.gd

可用脚本

Lambda 捕获清理(完整)

Godot 在节点释放时会自动断开大多数连接。**例外:**捕获局部变量的 lambda——必须手动断开连接。

var my_lambda: Callable

func _ready() -> void:
    var x := 10
    my_lambda = func(): print(x)
    player.died.connect(my_lambda)

func _exit_tree() -> void:
    if player and player.died.is_connected(my_lambda):
        player.died.disconnect(my_lambda)

重新指定目标时,优先使用命名方法或 disconnect_ghost_signals.gd。

CONNECT_REFERENCE_COUNTED — 正确语义

CONNECT_REFERENCE_COUNTED 表示多个相同的连接共享一个带引用计数的连接(连接 N 次 / 断开 N 次)。它不表示“发射器释放时自动清理”,也不能修复捕获 lambda 导致的泄漏。

  • 释放时自动清理:当任一端释放时,与 Object 方法的普通连接(非捕获)会被清除。
  • 捕获 lambda:始终需要手动 disconnect(见上文)。
  • 触发后自动移除的单次连接:CONNECT_ONE_SHOT。

深入教程(按需)

大模型无知规则:如果通用 Agent 在阅读前不会知道某项内容,它就应放在这里或 scripts/ 中——绝不删除,只能移动。

主题参考资料
模式 1–7 + 注意事项implementation-patterns.md

参考资料

渐进式披露:仅在研究特定 API 时打开官方文档链接;在路由到同领域时加载相关技能——不要预加载整个技能网络。

官方文档
  • 使用信号 — 核心的发射/连接模型,以及信号如何在不使用硬引用的情况下解耦节点。
  • 场景组织 — 经典的“向上发信号,向下调用”所有权规则,让父→子命令流保持明确。
  • 使用信号实例化 — 从生成的场景发射信号,让父节点/管理器接收子弹、战利品及其他产物,而不依赖固定节点路径。
  • Autoload 与常规节点 — 何时适合使用全局 EventBus,何时场景内的信号连接更安全。
  • 单例(Autoload) — 如何注册可跨场景切换而存在的类型化信号总线。
  • Signal — 类型化的 Signal API:emit、connect、is_connected 和本技能中使用的断开连接辅助方法。
  • Callable — 使用 bind() / unbind() 注入或丢弃回调上下文,无需包装 lambda。
  • Object — CONNECT_ONE_SHOT、CONNECT_DEFERRED、CONNECT_REFERENCE_COUNTED 和 CONNECT_APPEND_SOURCE_OBJECT 标志。
  • GDScript 基础 — 类型化的 signal 声明,以及在信号上使用 await 实现线性异步序列。
  • 使用 SceneTree — 进入/退出场景树时的连接生命周期,以及动态监听器在重新指定目标时必须断开连接的原因。
  • Godot 通知 — 关于 _ready、父节点缓存和用户信号的安全连接时机。
  • 空闲处理与物理处理 — 为什么回调会在物理步进期间修改物理实体时,延迟执行的信号处理函数很重要。
相关技能
前置技能
配套内容
  • godot-composition — 组件节点发出过去时事件;父节点通过连接这些信号并向下调用来进行组合。
  • godot-scene-management — 场景切换和加载器必须通过总线重新连接或重新发出信号,避免留下幽灵监听器。
  • godot-state-machine-advanced — 状态进入/退出通常会触发信号扇出;可避免 FSM 转换形成循环信号图。
  • godot-resource-data-patterns — 共享配置优先使用 Resources;信号用于传递变更事件,而非重复的可变状态数据块。
  • godot-testing-patterns — watch_signals / 间谍对象可与此技能的发出约定配合,用于单元测试和集成测试。
  • godot-ui-containers — 按钮和菜单应向上发出意图信号;控制器向下调用以更新 Control 树。
下游 / 消费方
  • godot-dialogue-system — 对话行/选项完成事件应遵循信号向上的编排方式,传递到 UI 和任务监听器。
  • godot-ability-system — 冷却、施法和命中数据载荷需要使用类型化信号,让 HUD/VFX 与能力节点保持解耦。
  • godot-combat-system — 伤害/死亡/得分链是信号向上扇出到 UI、音频和进度系统的典型场景。
  • godot-performance-optimization — 出现高频信号风暴时应升级处理;用缓冲区或直接读取替代逐帧信号。
主索引
  • godot-master — 技能库路由器和镜像模块入口;需要确定哪个领域技能负责跨领域架构问题时,请打开此项。

评论

支持 Markdown