Vampire-Act-Base/docs/architecture/adr-002.md

2.0 KiB

ADR-002: Event Bus & Cross-Layer Communication Pattern

Status: Accepted Date: 2026-04-27 Engine: Unity 2022.3.62f3c1 GDD Requirements Addressed: All L0→L1 communication from systems-index.md


Context

Architecture requires L0 to never call L1 or L2. All upward communication must go through an event mechanism. Need to choose: C# built-in event vs. a dedicated EventBus class. This decision affects every L0 module's interface design and memory safety.

Decision

Use C# built-in event + Action<T>. No dedicated EventBus class.

Rationale:

  • L0 has a fixed set of 10 modules — direct event declarations are manageable without a central registry
  • C# event provides compile-time type safety; parameter mismatches are caught at build time, not runtime
  • Zero external dependencies — no third-party messaging library
  • Each L0 module's events are part of its public API contract, visible and self-documenting for external developers

Subscription lifecycle:

L1/L2 subscribe to L0 events in OnEnable()
L1/L2 unsubscribe in OnDisable()
    (NOT OnDestroy — avoids lost subscriptions on disable/re-enable cycles)

Naming convention: On[What] — e.g., OnFormChanged, OnEnergyChanged, OnWaveStart

Parameter convention: Use lightweight structs or primitive types. Never pass mutable L0 internal object references to subscribers (prevents L1 from mutating L0 state).

Hot path exception: Attack resolution and damage calculation use per-frame method calls (CombatLogic.ResolveAttacks()), not events. Events are reserved for low-frequency state transition notifications.

Consequences

  • Each L0 module's event surface is explicitly visible, making inter-system communication self-documenting
  • No centralized message registry reduces coupling
  • L1 developers MUST follow OnEnable/OnDisable subscription discipline — leaks or null refs otherwise
  • If system count grows beyond ~20, a refactor to a dedicated EventBus may be warranted