跳到主要内容
知仓学习社ZHICANG

godot-signal-architecture

Expert blueprint for signal-driven architecture using \"Signal Up, Call Down\" pattern for loose coupling. Covers typed signals, signal chains, one-…

不碰外部(只输出文字)无严重或高危命中thedivergentai/GD-Agentic-Skills

它会碰到什么

扫了多少3 个文本文件,18 KB
它会碰到什么不碰外部(只输出文字)
命中总数0 处
命中统计严重 0 · 高 0 · 中 0 · 低 0

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

NEVER Do in Signal Architecture

  • NEVER use the legacy string-based Object.connect() — Typos result in silent failures. Always use signal.connect(_callback) for compile-time validation.
  • NEVER use signals to dictate behavior top-down — Signals are past-tense events (e.g., "died"). Use direct method calls for commands (e.g., "kill").
  • NEVER connect a signal twice to the same Callable — This throws an ERR_INVALID_PARAMETER at runtime unless using the Object.CONNECT_REFERENCE_COUNTED flag to stack connections.
  • NEVER use a Global Signal Bus for local data — Pollutes global state and makes debugging harder. Use local connections for scene-specific logic.
  • NEVER assume callbacks must accept all signal arguments — Use unbind() to drop unwanted parameters and keep your API clean.
  • NEVER create circular signal dependencies — A signals B, B signals back to A? Use a mediator (parent or AutoLoad) to break the loop.
  • NEVER skip signal typingsignal moved without types lacks editor support. Always use signal moved(dir: Vector2).
  • NEVER forget to disconnect dynamic signals — Ghost connections cause "call on null instance" errors. Disconnect in _exit_tree() or when retargeting ([disconnect_ghost_signals.gd](scripts/disconnect_ghost_signals.gd)).
  • NEVER emit signals with immediate side effects on the emitter — If died.emit() calls queue_free(), listeners might fail to respond. Emit first.
  • NEVER use signals for high-frequency data streams — Sending 1000+ signals/second (like per-particle updates) is inefficient. Use shared arrays or direct buffers.

Signal Up / Call Down

  • Children → parents: past-tense signals (health_changed, died).
  • Parents → children: direct calls / properties (apply_damage, play_anim).
  • Siblings: parent mediator or carefully scoped Autoload bus — never sibling hard refs.

Use signals for: UI presses, death → game over, loot → inventory, cross-scene bus events.

Use direct calls for: parent commanding child, local property access.

Decision Tree: Where to Connect

| Scope | Pattern | MANDATORY script |

|-------|---------|------------------|

| Child notifies parent / UI | Local signal.connect in parent _ready | [signal_up_call_down_pattern.gd](scripts/signal_up_call_down_pattern.gd) |

| Parent orchestrates children | Method calls down (not signals) | same |

| Cross-scene / systems (achievements, save) | Autoload bus | [global_signal_bus_router.gd](scripts/global_signal_bus_router.gd) / [global_event_bus.gd](scripts/global_event_bus.gd) |

| Linear async steps (load → fade → spawn) | await signal sequence | [await_signal_sequencing.gd](scripts/await_signal_sequencing.gd) / [complex_signal_sequencer.gd](scripts/complex_signal_sequencer.gd) |

| Retarget tracking (new enemy) | Disconnect old first | [disconnect_ghost_signals.gd](scripts/disconnect_ghost_signals.gd) |

| One-shot / physics-safe | CONNECT_ONE_SHOT / CONNECT_DEFERRED | [one_shot_deferred_connections.gd](scripts/one_shot_deferred_connections.gd) |

| Extra context / drop args | Callable.bind / unbind | [callable_bind_context.gd](scripts/callable_bind_context.gd) / [unbind_unwanted_args.gd](scripts/unbind_unwanted_args.gd) |

Available Scripts

  • [signal_up_call_down_pattern.gd](scripts/signal_up_call_down_pattern.gd) — MANDATORY before hierarchy wiring.
  • [global_signal_bus_router.gd](scripts/global_signal_bus_router.gd) / [global_event_bus.gd](scripts/global_event_bus.gd) — MANDATORY before Autoload buses.
  • [disconnect_ghost_signals.gd](scripts/disconnect_ghost_signals.gd) — MANDATORY when switching tracked emitters.
  • [await_signal_sequencing.gd](scripts/await_signal_sequencing.gd) / [complex_signal_sequencer.gd](scripts/complex_signal_sequencer.gd) — MANDATORY for multi-step awaits.
  • [safe_dynamic_connections.gd](scripts/safe_dynamic_connections.gd) — is_connected guards.
  • [one_shot_deferred_connections.gd](scripts/one_shot_deferred_connections.gd) — one-shot / deferred flags.
  • [callable_bind_context.gd](scripts/callable_bind_context.gd) / [unbind_unwanted_args.gd](scripts/unbind_unwanted_args.gd) — bind/unbind.
  • [track_signal_emitter_source.gd](scripts/track_signal_emitter_source.gd) — CONNECT_APPEND_SOURCE_OBJECT.
  • [signal_debugger.gd](scripts/signal_debugger.gd) / [signal_spy.gd](scripts/signal_spy.gd) — debug / test spies.

Lambda Capture Cleanup (complete)

Godot auto-disconnects most connections when a node frees. Exception: lambdas that capture locals — you must disconnect manually.

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)

Prefer named methods or [disconnect_ghost_signals.gd](scripts/disconnect_ghost_signals.gd) when retargeting.

CONNECT_REFERENCE_COUNTED — Correct Semantics

CONNECT_REFERENCE_COUNTED means multiple identical connects share one connection with a refcount (connect N times / disconnect N times). It is not "auto-cleanup when the emitter frees" and does not fix capturing-lambda leaks.

  • Auto-cleanup on free: normal connections to Object methods (non-capturing) are cleared when either side is freed.
  • Capturing lambdas: always manual disconnect (see above).
  • One-shot auto-remove after fire: CONNECT_ONE_SHOT.

Deep recipes (on demand)

> LLM-ignorance rule: if a general agent would not know it before reading, it lives here or in scripts/ — never delete, only move.

| Topic | Reference |

|-------|-----------|

| Patterns 1–7 + gotchas | [implementation-patterns.md](references/implementation-patterns.md) |

Reference

> Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.

Official Documentation

  • Using signals — Core emit/connect model and why signals decouple nodes without hard references.
  • Scene organization — Canonical “signal up, call down” ownership rules that keep parent→child command flows explicit.
  • Instancing with signals — Emit from spawned scenes so parents/managers receive bullets, loot, and other products without fixed node paths.
  • Autoloads versus regular nodes — When a global EventBus is justified vs when scene-local signal wiring is safer.
  • Singletons (Autoload) — How to register a typed signal bus that survives scene changes.
  • Signal — Typed Signal API: emit, connect, is_connected, and disconnect helpers used throughout this skill.
  • Callablebind() / unbind() for injecting or discarding callback context without wrapper lambdas.
  • ObjectCONNECT_ONE_SHOT, CONNECT_DEFERRED, CONNECT_REFERENCE_COUNTED, and CONNECT_APPEND_SOURCE_OBJECT flags.
  • GDScript basics — Typed signal declarations and await on signals for linear async sequences.
  • Using SceneTree — Connection lifetime across enter/exit tree and why dynamic listeners must disconnect when retargeting.
  • Godot notifications — Safe connection timing relative to _ready, parent caches, and user signals.
  • Idle and Physics Processing — Why deferred signal handlers matter when callbacks mutate physics bodies mid-step.

Related Skills

Prerequisites

  • godot-project-foundations — Project layout, Autoload registration, and scene ownership conventions signals plug into.
  • godot-gdscript-mastery — Typed Callables, await, and signal syntax required before advanced connect flags and sequencers.
  • godot-autoload-architecture — Singleton boot order and ownership rules for global EventBus routers (not for local scene events).

Complements

  • godot-composition — Component nodes emit past-tense events; parents compose by connecting those signals and calling down.
  • godot-scene-management — Scene swaps and loaders must reconnect or re-emit through buses without ghost listeners.
  • godot-state-machine-advanced — State enter/exit often drives signal fan-out; keeps FSM transitions from becoming circular signal graphs.
  • godot-resource-data-patterns — Prefer Resources for shared config; signals carry change events, not duplicated mutable state blobs.
  • godot-testing-patternswatch_signals / spies pair with this skill’s emit contracts for unit and integration tests.
  • godot-ui-containers — Buttons and menus should signal intent upward; controllers call down to update Control trees.

Downstream / consumers

  • godot-dialogue-system — Line/choice completion events should follow signal-up orchestration into UI and quest listeners.
  • godot-ability-system — Cooldown, cast, and hit payloads need typed signals so HUD/VFX stay decoupled from ability nodes.
  • godot-combat-system — Damage/death/score chains are the classic signal-up fan-out into UI, audio, and progression.
  • godot-performance-optimization — Escalate when high-frequency emit storms show up; replace per-tick signals with buffers or direct reads.

Master

  • godot-master — Library router and mirrored module entry; open when discovering which Domain Skill owns a cross-cutting architecture concern.

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。