godot-signal-architecture
Expert blueprint for signal-driven architecture using "Signal Up, Call Down" pattern for loose coupling. Covers typed signals, signal chains, one-shot connections, and AutoLoad event buses. Use when implementing event systems OR decoupling nodes. Keywords signal, emit, connect, CONNECT_ONE_SHOT, CON
By thedivergentai · 381 installs
npx skills add thedivergentai/gd-agentic-skills --skill godot-signal-architecture
Source repository · Upstream listing
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 typing — signal 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.
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](https://docs.godotengine.org/en/stable/getting started/step by step/signals.html) — Core emit/connect model and why signals decouple nodes without hard references.
[Scene organization](https://docs.godotengine.org/en/stable/tutorials/best practices/scene organization.html) — Canonical “signal up, call down” ownership rules that keep parent→child command flows explicit.
[Instancing with signals](https://docs.godotengine.org/en/stable/tutorials/scripting/instancing with signals.html) — Emit from spawned scenes so parents/managers receive bullets, loot, and other products without fixed node paths.
[Autoloads versus regular nodes](https://docs.godotengine.org/en/stable/tutorials/best practices/autoloads versus regular nodes.html) — When a global EventBus is justified vs when scene local signal wiring is safer.
[Singletons (Autoload)](https://docs.godotengine.org/en/stable/tutorials/scripting/singletons autoload.html) — How to register a typed signal bus that survives scene changes.
[Signal](https://docs.godotengine.org/en/stable/classes/class signal.html) — Typed Signal API: emit , connect , is connected , and disconnect helpers used throughout this skill.
[Callable](https://docs.godotengine.org/en/stable/classes/class callable.html) — bind() / unbind() for injecting or discarding callback context without wrapper lambdas.
[Object](https://docs.godotengine.org/en/stable/classes/class object.html) — CONNECT ONE SHOT , CONNECT DEFERRED , CONNECT REFERENCE COUNTED , and CONNECT APPEND SOURCE OBJECT flags.
[GDScript basics](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript basics.html) — Typed signal declarations and await on signals for linear async sequences.
[Using SceneTree](https://docs.godotengine.org/en/stable/tutorials/scripting/scene tree.html) — Connection lifetime across enter/exit tree and why dynamic listeners must disconnect when retargeting.
[Godot notifications](https://docs.godotengine.org/en/stable/tutorials/best practices/godot notifications.html) — Safe connection timing relative to ready , parent caches, and user signals.
[Idle and Physics Processing](https://docs.godotengine.org/en/stable/tutorials/scripting/idle and physics processing.html) — Why deferred signal handlers matter when callbacks mutate physics bodies mid step.
Related Skills
Prerequisites
[godot project foundations](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot project foundations/SKILL.md) — Project layout, Autoload registration, and scene ownership conventions signals plug into.
[godot gdscript mastery](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot gdscript mastery/SKILL.md) — Typed Callables, await , and signal syntax required before advanced connect flags and sequencers.
[godot autoload architecture](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot autoload architecture/SKILL.md) — Singleton boot order and ownership rules for global EventBus routers (not for local scene events).
Complements
[godot composition](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot composition/SKILL.md) — Component nodes emit past tense events; parents compose by connecting those signals and calling down.
[godot scene management](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot scene management/SKILL.md) — Scene swaps and loaders must reconnect or re emit through buses without ghost listeners.
[godot state machine advanced](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot state machine advanced/SKILL.md) — State enter/exit often drives signal fan out; keeps FSM transitions from becoming circular signal graphs.
[godot resource data patterns](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot resource data patterns/SKILL.md) — Prefer Resources for shared config; signals carry change events, not duplicated mutable state blobs.
[godot testing patterns](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot testing patterns/SKILL.md) — watch signals / spies pair with this skill’s emit contracts for unit and integration tests.
[godot ui containers](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot ui containers/SKILL.md) — Buttons and menus should signal intent upward; controllers call down to update Control trees.
Downstream / consumers
[godot dialogue system](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot dialogue system/SKILL.md) — Line/choice completion events should follow signal up orchestration into UI and quest listeners.
[godot ability system](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot ability system/SKILL.md) — Cooldown, cast, and hit payloads need typed signals so HUD/VFX stay decoupled from ability nodes.
[godot combat system](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot combat system/SKILL.md) — Damage/death/score chains are the classic signal up fan out into UI, audio, and progression.
[godot performance optimization](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot performance optimization/SKILL.md) — Escalate when high frequency emit storms show up; replace per tick signals with buffers or direct reads.
Master
[godot master](https://github.com/thedivergentai/gd agentic skills/blob/main/skills/godot master/SKILL.md) — Library router and mirrored module entry; open when discovering which Domain Skill owns a cross cutting architecture concern.