Skip to main content

14 Runtime Monitor: Production Observability

๐Ÿ“‹ Overviewโ€‹

In production, events fire thousands of times per second. Debug.Log() creates garbage, floods the console, and provides no structured insight into system health. You need enterprise-grade observabilityโ€”real-time performance profiling, listener tracking, frequency analysis, and integrity warnings.

The Game Event Monitor is a specialized debugging window that answers critical questions:

  • "Which event is causing that frame drop?"
  • "Is this event firing too often?"
  • "Who is actually listening to this event right now?"
  • "Why did my chain sequence break?"

This demo simulates a high-load stress test facility with four specialized test units, each designed to populate specific Monitor tabs with diagnostic data.

๐Ÿ’ก What You'll Learn
  • How to open and navigate the Runtime Monitor window
  • Reading performance metrics (avg/min/max execution time)
  • Analyzing event frequency and detecting spam
  • Inspecting listener counts (Inspector vs API bindings)
  • Visualizing programmatic Flow Graphs
  • Detecting integrity issues (ghost events, broken chains)
  • Interpreting warnings and health indicators

๐ŸŽฌ Demo Sceneโ€‹

Assets/TinyGiants/GameEventSystem/Demo/14_RuntimeMonitor/14_RuntimeMonitor.unity

Scene Compositionโ€‹

Visual Elements:

  • ๐ŸŽฏ Test Console - Information panel describing 4 test units
  • ๐ŸงŠ Simple Geometry - Plane and Cube (minimal scene)

UI Layer (Canvas):

  • ๐ŸŽฎ Four Control Buttons - Bottom of screen
    • "Toggle Spammer (Unit A)" โ†’ Starts/stops high-frequency spam
    • "Trigger Heavy Load (Unit B)" โ†’ Fires expensive operation
    • "Fire Chain Reaction (Unit C)" โ†’ Executes programmatic chain
    • "Fire Ghost Event (Unit D)" โ†’ Raises event with no listeners

Game Logic Layer:

  • ๐Ÿ“ค RuntimeMonitorRaiser - Test orchestrator
  • ๐Ÿ“ฅ RuntimeMonitorReceiver - Test responder with instrumented listeners

๐Ÿงช The 4 Test Unitsโ€‹

Each unit is designed to stress-test a specific Monitor subsystem:

Unit A: The Spammer (Frequency Test)โ€‹

Purpose: Generate high-frequency event spam to test Statistics tab

Configuration:

  • Events: OnSpammer (void), OnSpammerPersistent (void)
  • Behavior: Fires >60 times/second in Update() while active
  • Monitor Goal: Detect high-frequency warnings

Expected Results:

  • ๐Ÿ“ˆ Statistics Tab: Shows >60 fires/sec (RED warning)
  • โš ๏ธ Warnings Tab: Flags [High Frequency] issue

Unit B: The Heavy Lifter (Performance Test)โ€‹

Purpose: Simulate expensive computation to test Performance tab

Configuration:

  • Events: OnHeavyLoad, OnHeavyLoadCondition (GameObject, DamageInfo)
  • Behavior: Listener calls Thread.Sleep(6) to simulate 6ms+ lag
  • Monitor Goal: Trigger performance warnings

Expected Results:

  • โšก Performance Tab: Execution time shows 6-12ms (YELLOW/RED)
  • ๐Ÿ“Š Dashboard: Performance bar turns yellow/red

Code Mechanism:

public void OnHeavyExecution(GameObject sender, DamageInfo info)
{
// Simulate heavy computation (BAD in production, perfect for testing!)
Thread.Sleep(6); // โ† Forces 6ms execution time
}

Unit C: The Chain Reactor (Automation Test)โ€‹

Purpose: Demonstrate programmatic Flow Graph visualization

Configuration:

  • Events: OnChainStart โ†’ OnChainProcess โ†’ OnChainFinish โ†’ OnTriggerComplete
  • Behavior: Code-built sequential pipeline with delays and conditions
  • Monitor Goal: Visualize dynamic automation in Automation tab

Graph Structure:

๐Ÿš€ [ START ] OnChainStart (DamageInfo)
โ”‚ โž” Payload: { amount: 75.0, type: Physical, ... }
โ”‚
โ”œโ”€ โฑ๏ธ [ STEP 1 ] โž” Delay: 0.5s
โ”‚ โ””โ”€โ–บ โš™๏ธ OnChainProcess (DamageInfo) โœ… Data Relayed
โ”‚
โ”œโ”€ โš–๏ธ [ STEP 2 ] โž” Delay: 0.2s | Guard: `amount > 50`
โ”‚ โ””โ”€โ–บ ๐ŸŽฏ OnChainFinish (DamageInfo) โœ… Logic Passed (75 > 50)
โ”‚
โ””โ”€ ๐Ÿงน [ STEP 3 ] โž” Trigger Mode | Block Args
โ””โ”€โ–บ ๐Ÿ OnTriggerComplete (void) โœ… Signal Purified
โ”‚
๐Ÿ“Š Result: Pipeline Completed | ๐Ÿ›ก๏ธ Data Safety: Argument Blocked at Exit

Expected Results:

  • ๐Ÿ”— Automation Tab: Shows hierarchical tree with timing/condition badges
  • ๐Ÿ“ Recent Events Tab: Sequential firing pattern visible

Unit D: The Ghost (Integrity Test)โ€‹

Purpose: Detect events fired with no listeners

Configuration:

  • Event: OnGhost (void)
  • Behavior: Raises event with zero listeners bound
  • Monitor Goal: Trigger integrity warning

Expected Results:

  • โš ๏ธ Warnings Tab: Shows [No Listeners] warning
  • ๐Ÿ“Š Dashboard: Warning count increases

๐ŸŽฎ How to Test (Step-by-Step)โ€‹

Phase 1: Preparationโ€‹

Step 1: Open Monitor Window

  • Menu

    The utility is located within the Game Event System, you can access through the following method:

    From the System Dashboard:

    Game Event System Window โ†’ Click "Game Event Monitor"
  • Window appears

    dockable like any Unity Editor window

Step 2: Enter Play Mode

  • Click Unity's Play button
  • Monitor remains visible during play

Phase 2: Generate Test Dataโ€‹

Step 3: Activate Unit A (Spammer)

  • Click "Toggle Spammer (Unit A)" button
  • Observe: Button stays active (toggled ON)
  • Effect: OnSpammer fires >60 times/second

Step 4: Activate Unit B (Heavy Load)

  • Click "Trigger Heavy Load (Unit B)" button 3-5 times
  • Effect: Each click triggers one expensive operation (6ms lag)

Step 5: Activate Unit C (Chain Reaction)

  • Click "Fire Chain Reaction (Unit C)" button once
  • Effect: Initiates 4-step sequential pipeline

Step 6: Activate Unit D (Ghost Event)

  • Click "Fire Ghost Event (Unit D)" button once
  • Effect: Raises event with no listeners (integrity violation)
โฑ๏ธ Wait Time

After triggering all units, wait 5-10 seconds to accumulate data before analyzing Monitor tabs.


๐Ÿ“Š Monitor Window Analysisโ€‹

Tab 1: ๐Ÿ  Dashboard (System Health Overview)โ€‹

The landing pageโ€”aggregates metrics from all subsystems into a single health report.

Monitor Dashboard

Metric Cards (Top Row):

CardMeaningExpected Value
Total EventsLoaded event count9
Total LogsCumulative fires since play start500+ (climbing)
MonitoredEvents with active performance tracking4-6
WarningsCurrent active issues2+ (Spam + Ghost)

Active Databases Section:

  • Lists all loaded database assets
  • PRIMARY badge shows main database
  • Click database name to filter views

Performance Overview (Traffic Light Bar):

  • ๐ŸŸข Green: All events <1ms (healthy)
  • ๐ŸŸก Yellow: Some events 1-5ms (caution)
  • ๐Ÿ”ด Red: Events >5ms detected (critical)
  • Shows percentage distribution

Recent Activity (Mini-Log):

  • Last 15 event firings
  • Format: [Frame] EventName (args)
  • Click to jump to Details tab

Quick Warnings (Top 3):

  • Most critical alerts surfaced
  • Severity icons: ๐Ÿ”ต Info, ๐ŸŸก Warning, ๐Ÿ”ด Critical
  • Click to jump to Warnings tab
๐ŸŽฏ Dashboard Purpose

Single-glance system health checkโ€”like a car's instrument panel. If this shows red/yellow, drill into specific tabs for diagnosis.


Tab 2: โšก Performance (Execution Profiling)โ€‹

Focus: Detect performance bottlenecks by execution time

Monitor Performance

Columns:

ColumnMeaningHealthy Range
Event NameEvent identifier-
Avg TimeAverage execution ms<1ms ๐ŸŸข
Min TimeFastest execution-
Max TimeSlowest execution<5ms ๐ŸŸก, >5ms ๐Ÿ”ด
ListenersAvg listener count per fire-
GC AllocGarbage generated per fire0 KB ideal

Color Coding:

  • ๐ŸŸข Green: 0-1ms (excellent)
  • ๐ŸŸก Yellow: 1-5ms (monitor)
  • ๐Ÿ”ด Red: >5ms (investigate)

Test Results (Unit B):

  1. Locate OnHeavyLoad event in table
  2. Avg Time: Shows ~6.00ms (๐ŸŸก Yellow)
  3. Max Time: May show ~12.00ms if clicked multiple times (๐Ÿ”ด Red)
  4. Cause: Thread.Sleep(6) in listener code

Usage:

  • Sort by "Avg Time" to find worst offenders
  • Click event name to see Details tab
  • Compare listener countsโ€”more listeners = higher risk
โš ๏ธ Performance Budget

General rule: Keep avg execution time <1ms. Budget total frame time (16ms @ 60fps) across all systems.


Tab 3: ๐Ÿ“ Recent Events (Real-Time Event Log)โ€‹

Focus: Chronological stream of all event firings

Monitor Recent

Columns:

ColumnMeaningExample
FrameUnity frame numberF:1450
TimeTimestamp since play start12.45s
EventEvent nameOnHeavyLoad
ArgumentsPayload preview<DamageInfo: 100>
CallerMethod that called .Raise()RuntimeMonitorRaiser.TriggerHeavyLoad

Features:

  • ๐Ÿ” Search: Filter by event name
  • ๐Ÿ“‹ Stack Trace: Toggle to see full call stack
  • ๐Ÿ”— Details Link: Click event to see deep dive

Test Results (All Units):

  • Unit A: Rapid succession of OnSpammer entries (60+/sec)
  • Unit C: Sequential pattern: OnChainStart โ†’ (delay) โ†’ OnChainProcess โ†’ OnChainFinish โ†’ OnTriggerComplete
  • Unit D: Single OnGhost entry

Usage:

  • Verify event firing order (sequential vs parallel)
  • Debug unexpected event triggers
  • Investigate caller methods (who's raising this?)
๐ŸŽฏ Pro Tip

Unlike Unity Console, this log is specialized for eventsโ€”no noise from other Debug.Log calls, structured data preview, direct caller info.


Tab 4: ๐Ÿ“ˆ Statistics (Frequency Analysis)โ€‹

Focus: Long-term usage patterns and frequency tracking

Monitor Statistics

Columns:

ColumnMeaningHealthy Range
Event NameEvent identifier-
Trigger CountTotal fires since play start-
Freq/secFires per second<10 ๐ŸŸข, 10-30 ๐ŸŸก, >30 ๐Ÿ”ด
Avg IntervalTime between fires (ms)>100ms ideal
Last TriggerTime since last fire-

Test Results (Unit A):

  1. Locate OnSpammer event
  2. Trigger Count: Rapidly climbing (1000+ after 10sec)
  3. Freq/sec: Shows >60/s (๐Ÿ”ด Red warning)
  4. Avg Interval: Shows ~16ms (every frame at 60fps)

Warning Triggers:

  • ๐ŸŸก Yellow: 10-30 fires/sec
  • ๐Ÿ”ด Red: >30 fires/sec (potential performance issue)

Usage:

  • Identify event spam (too frequent)
  • Detect idle events (never firing)
  • Analyze firing patterns over time
๐Ÿšจ Frequency Red Flags
  • >60/sec: Likely firing every frameโ€”consider batching
  • Irregular spikes: May indicate logic bug
  • Zero frequency: Dead code or misconfigured event

Tab 5: โš ๏ธ Warnings (Integrity & Health Alerts)โ€‹

Focus: Filter noise, surface critical issues

Monitor Warnings

Severity Levels:

IconLevelMeaning
๐Ÿ”ตInfoAdvisory notice (FYI)
๐ŸŸกWarningNon-critical issue (monitor)
๐Ÿ”ดCriticalSevere problem (fix immediately)

Warning Types:

WarningTriggerSeverity
[No Listeners]Event raised but no listeners bound๐Ÿ”ต Info
[High Frequency]Fires >30 times/sec๐ŸŸก Warning
[Performance]Execution time >5ms๐Ÿ”ด Critical
[GC Pressure]Garbage allocation >1KB/fire๐ŸŸก Warning

Test Results:

  • Unit A: OnSpammer - [High Frequency] Firing at 62/sec
  • Unit D: OnGhost - [No Listeners] Event raised with zero subscribers

Usage:

  • Check after major feature additions
  • Monitor during stress tests
  • Ignore expected warnings (e.g., debug events)
๐ŸŽ“ Ghost Events

[No Listeners] warnings are usually bugsโ€”either:

  1. Listener registration failed (check OnEnable)
  2. Event asset reference is wrong
  3. Dead code (remove the .Raise() call)

Tab 6: ๐Ÿ‘‚ Listeners (Subscription Inspector)โ€‹

Focus: Granular breakdown of WHO is listening

Monitor Listeners

Select an event (e.g., OnHeavyLoad) to see detailed breakdown:

Listener Categories:

CategoryMeaningIcon
BasicStandard AddListener๐Ÿ“Œ
PriorityAddPriorityListener with priority value๐Ÿ”ข
ConditionalAddConditionalListener with predicateโœ…
PersistentAddPersistentListener (survives scenes)๐Ÿงฌ

Breakdown Grid:

๐Ÿ“Š Total Active Listeners: 5
โ”‚
โ”œโ”€ ๐Ÿ”— Basic Listeners (1)
โ”‚ โ”œโ”€ ๐Ÿ“ฆ Inspector Bindings: 0
โ”‚ โ””โ”€ ๐Ÿ’ป API Bindings: 1
โ”‚ โ””โ”€ โš™๏ธ RuntimeMonitorReceiver.OnHeavyExecution
โ”‚
โ”œโ”€ โš–๏ธ Priority Queue (3)
โ”‚ โ”œโ”€ ๐Ÿฅ‡ High Priority (100): 1
โ”‚ โ”‚ โ””โ”€ โš™๏ธ RuntimeMonitorReceiver.OnHeavyPreCheck
โ”‚ โ”œโ”€ ๐Ÿฅˆ Normal Priority (0): 1
โ”‚ โ”‚ โ””โ”€ โš™๏ธ RuntimeMonitorReceiver.OnHeavyExecution
โ”‚ โ””โ”€ ๐Ÿฅ‰ Low Priority (-100): 1
โ”‚ โ””โ”€ โš™๏ธ RuntimeMonitorReceiver.OnHeavyPostCheck
โ”‚
โ”œโ”€ ๐Ÿ›ก๏ธ Conditional Guards (1)
โ”‚ โ””โ”€ ๐Ÿ’Ž [Prio: 50] RuntimeMonitorReceiver.OnHeavyCriticalWarning
โ”‚ โ””โ”€ ๐Ÿ” Predicate: (sender, info) => info.isCritical
โ”‚
โ””โ”€ ๐Ÿ’Ž Persistent Registry (0)
โ””โ”€ (No cross-scene listeners active)

Test Results (Unit B):

  • Total: 4-5 listeners
  • Priority Distribution: High (1), Normal (1), Low (1)
  • Conditional: 1 (with predicate preview)

Usage:

  • Verify code-based registrations worked
  • Check listener execution order (priority values)
  • Debug missing listeners (expected vs actual count)
  • Audit persistent listeners (memory leak prevention)
๐Ÿ” Inspector vs API
  • Inspector Bindings: Configured in Behavior window
  • API Bindings: Registered via AddListener in code
  • Both show up hereโ€”validates your hybrid approach

Tab 7: ๐Ÿ”— Automation (Programmatic Flow Visualization)โ€‹

Focus: Visualize code-built Trigger/Chain graphs

Monitor Automation

Tree View Structure:

โ–ผ OnChainStart (Root, <DamageInfo>)
โ”‚
โ”œโ”€ ๐Ÿ”— Chain โ†’ OnChainProcess
โ”‚ โ”œโ”€ โฑ๏ธ Delay: 0.5s
โ”‚ โ”œโ”€ โœ… Pass Argument
โ”‚ โ””โ”€ Type: <DamageInfo>
โ”‚
โ””โ”€ (OnChainProcess expanded)
โ”‚
โ”œโ”€ ๐Ÿ”— Chain โ†’ OnChainFinish
โ”‚ โ”œโ”€ โฑ๏ธ Delay: 0.2s
โ”‚ โ”œโ”€ ๐Ÿงฉ Condition: info.amount > 50
โ”‚ โ”œโ”€ โœ… Pass Argument
โ”‚ โ””โ”€ Type: <DamageInfo>
โ”‚
โ””โ”€ (OnChainFinish expanded)
โ”‚
โ””โ”€ ๐Ÿ•น๏ธ Trigger โ†’ OnTriggerComplete
โ”œโ”€ โŒ Block Argument
โ””โ”€ Type: (void)

Badge Legend:

BadgeMeaning
โฑ๏ธ 0.5sDelay configured
๐ŸงฉCondition enabled
โœ…Argument passing enabled
โŒArgument blocked
๐Ÿ”—Chain node (sequential)
๐Ÿ•น๏ธTrigger node (parallel)

Test Results (Unit C):

  • Root: OnChainStart
  • Depth: 3 levels (Start โ†’ Process โ†’ Finish โ†’ Complete)
  • Mixed Types: Chain (sequential) + Trigger (parallel) combined

Usage:

  • Verify programmatic graphs built correctly
  • Debug broken chains (missing nodes)
  • Visualize complex automation without opening Flow Graph window
  • Compare code-built vs visual-built graphs
๐ŸŽจ Code vs Visual Graphs
  • This tab: Shows code-built graphs (AddChainEvent, AddTriggerEvent)
  • Flow Graph window: Shows visual-built graphs (created via UI)
  • Both are valid, both are debuggable

Tab 8: ๐Ÿ” Event Details (Deep Dive)โ€‹

Focus: Single-event analysis and history

Monitor Details

Click "Details" or "View" from any other tab to drill down.

Sections:

1. Metadata:

  • GUID: Unique identifier (immutable)
  • Type: Full generic signature
  • Category: Organizational tag
  • Database: Source asset file

2. Performance Summary:

  • Avg/Min/Max Time: Same as Performance tab
  • GC Allocation: Memory profile
  • Listener Count: Current subscribers

3. Frequency Summary:

  • Total Fires: Since play start
  • Fires/Sec: Current rate
  • Avg Interval: Between fires
  • Last Fire: Time ago

4. Recent Activity (Filtered):

  • Event-specific log stream
  • Only shows this event's history
  • Full stack traces available

5. Automation (If Applicable):

  • Shows this event's place in Flow Graph
  • Upstream/downstream connections

Usage:

  • Comprehensive single-event analysis
  • Compare before/after optimization
  • Export data for team review

๐Ÿ—๏ธ Scene Architectureโ€‹

Event Organizationโ€‹

Events organized by test unit in Game Event Editor:

Game Event Editor

CategoryEvent NameTypePurpose
Unit AOnSpammerGameEventHigh-frequency spam
Unit AOnSpammerPersistentGameEventPersistent spam
Unit BOnHeavyLoadGameEvent<GameObject, DamageInfo>Performance test
Unit BOnHeavyLoadConditionGameEvent<GameObject, DamageInfo>Conditional test
Unit COnChainStartGameEvent<DamageInfo>Root (gold)
Unit COnChainProcessGameEvent<DamageInfo>Chain step 1
Unit COnChainFinishGameEvent<DamageInfo>Chain step 2
Unit COnTriggerCompleteGameEventChain step 3 (trigger)
Unit DOnGhostGameEventIntegrity test

Flow Graph Configurationโ€‹

Programmatic chain built in code:

Flow Graph

Graph Structure:

  • ๐Ÿ”ด OnChainStart (Root, Red) - Entry point
  • ๐ŸŸข OnChainProcess (Chain, Green) - Step 1 (Delay: 0.5s)
  • ๐ŸŸข OnChainFinish (Chain, Green) - Step 2 (Delay: 0.2s, Condition: amount > 50)
  • ๐ŸŸก OnTriggerComplete (Trigger, Yellow) - Step 3 (Argument blocked)

Connection Types:

  • ๐ŸŸข Green "CHAIN" lines - Sequential execution
  • ๐ŸŸก Yellow "TRIGGER" line - Parallel execution

Raiser Setup (RuntimeMonitorRaiser)โ€‹

RuntimeMonitorRaiser Inspector

Unit A: Frequency Test

  • On Spam Event: OnSpammer
  • On Spam Persistent Event: OnSpammerPersistent

Unit B: Performance Test

  • On Heavy Load Event: OnHeavyLoad
  • On Heavy Load Condition Event: OnHeavyLoadCondition

Unit C: Automation Test (Roots)

  • On Chain Start: OnChainStart

Unit C: Automation Test (Targets)

  • On Chain Process: OnChainProcess
  • On Chain Finish: OnChainFinish
  • On Trigger Complete: OnTriggerComplete

Unit D: Integrity Test

  • On Ghost Event: OnGhost

Receiver Setup (RuntimeMonitorReceiver)โ€‹

RuntimeMonitorReceiver Inspector

Events (Asset References):

  • Same events as Raiser

Chain Events (For Inspector Binding):

  • On Chain Process, On Chain Finish, On Trigger Complete
  • These have Inspector-based listeners (drag & drop in Behavior window)
  • Complements code-based API listeners

๐Ÿ’ป Code Breakdownโ€‹

Simulating Performance Issues (Unit B)โ€‹

RuntimeMonitorReceiver.cs - Heavy Execution:

public void OnHeavyExecution(GameObject sender, DamageInfo info)
{
// โš ๏ธ INTENTIONAL LAG FOR TESTING
// In production, NEVER use Thread.Sleep in game logic!
// This forces execution time to >5ms to trigger Monitor warnings
Thread.Sleep(6); // โ† Simulates expensive computation

Debug.Log($"[Receiver] Processed heavy data. Latency: 6ms (simulated)");
}

Why this works:

  • Thread.Sleep(6) blocks main thread for 6 milliseconds
  • Monitor's Performance tab tracks execution time per listener
  • 6ms exceeds 5ms threshold โ†’ triggers YELLOW warning
  • Click button 2x with Thread.Sleep(12) โ†’ RED critical warning

Building Programmatic Automation (Unit C)โ€‹

RuntimeMonitorRaiser.cs - Awake() Graph Construction:

private ChainHandle _chainProcessHandle;
private ChainHandle _chainFinishHandle;
private TriggerHandle _triggerCompleteHandle;

private void Awake()
{
// โœ… BUILD CHAIN IN CODE (Not visual graph!)

// Step 1: Start โ†’ (Delay 0.5s) โ†’ Process
_chainProcessHandle = onChainStart.AddChainEvent(
targetEvent: onChainProcess,
delay: 0.5f, // โ† Pause for half a second
passArgument: true // โ† Forward DamageInfo
);

// Step 2: Process โ†’ (Condition + Delay 0.2s) โ†’ Finish
_chainFinishHandle = onChainProcess.AddChainEvent(
targetEvent: onChainFinish,
delay: 0.2f,
condition: (info) => info.amount > 50f, // โ† Only high damage continues
passArgument: true
);

// Step 3: Finish โ†’ (Trigger, Block Args) โ†’ Complete
_triggerCompleteHandle = onChainFinish.AddTriggerEvent(
targetEvent: onTriggerComplete,
passArgument: false // โ† Block arguments (type conversion void)
);
}

private void OnDestroy()
{
// โœ… CLEANUP: MANDATORY for dynamic graphs
onChainStart.RemoveChainEvent(_chainProcessHandle);
onChainProcess.RemoveChainEvent(_chainFinishHandle);
onChainFinish.RemoveTriggerEvent(_triggerCompleteHandle);
}

Graph Execution Flow:

๐Ÿ–ฑ๏ธ User Interaction: Button Clicked
โ”‚
๐Ÿš€ [ INITIATION ] โž” onChainStart.Raise(DamageInfo)
โ”‚ ๐Ÿ“ฆ Payload: { amount: 100, isCritical: true }
โ”‚
โณ [ SCHEDULING ] โž” System Pauses for 0.5s
โ”‚ โ””โ”€โ–บ โš™๏ธ onChainProcess.Raise(DamageInfo)
โ”‚
โš–๏ธ [ EVALUATION ] โž” Gate: `100 > 50` ?
โ”‚ โ””โ”€โ–บ โœ… Result: YES (Condition Passed)
โ”‚
โณ [ SCHEDULING ] โž” System Pauses for 0.2s
โ”‚ โ””โ”€โ–บ ๐ŸŽฏ onChainFinish.Raise(DamageInfo)
โ”‚
๐Ÿงช [ PURIFICATION ] โž” Parameter Stripping: `DamageInfo` โž” `void`
โ”‚ โ””โ”€โ–บ ๐Ÿ onTriggerComplete.Raise()
โ”‚
๐Ÿ“Š Final Outcome: Pipeline Finalized | โšก Timing: 0.7s Total Delay

Monitor Visibility:

  • Automation Tab: Shows this exact tree structure
  • Recent Events Tab: Shows sequential firing pattern with timing
  • Performance Tab: Tracks each step's execution time

Registering Multi-Priority Listeners (Unit B)โ€‹

RuntimeMonitorReceiver.cs - OnEnable():

private void OnEnable()
{
// โœ… POPULATE LISTENERS TAB WITH VARIETY

// Basic listener (no priority)
onSpamEvent.AddListener(OnSpamReceived);

// Priority listeners (execution order)
onHeavyLoadEvent.AddPriorityListener(OnHeavyPreCheck, priority: 100); // Runs 1st
onHeavyLoadEvent.AddPriorityListener(OnHeavyExecution, priority: 0); // Runs 2nd (lag here)
onHeavyLoadEvent.AddPriorityListener(OnHeavyPostCheck, priority: -100); // Runs 3rd

// Conditional listener with priority
onHeavyLoadConditionEvent.AddConditionalListener(
OnHeavyCriticalWarning,
predicate: (sender, info) => info.isCritical, // โ† Only if critical
priority: 50
);
}

private void OnDisable()
{
// โœ… CLEANUP
onSpamEvent.RemoveListener(OnSpamReceived);

onHeavyLoadEvent.RemovePriorityListener(OnHeavyPreCheck);
onHeavyLoadEvent.RemovePriorityListener(OnHeavyExecution);
onHeavyLoadEvent.RemovePriorityListener(OnHeavyPostCheck);

onHeavyLoadConditionEvent.RemoveConditionalListener(OnHeavyCriticalWarning);
}

Monitor Visibility:

  • Listeners Tab: Shows 4 listeners for OnHeavyLoad
    • Priority breakdown: High (1), Normal (1), Low (1)
    • Conditional (1) with predicate preview
  • Performance Tab: Tracks cumulative execution time (sum of all listeners)

Persistent Listener Management (Unit A)โ€‹

RuntimeMonitorReceiver.cs - Awake/OnDestroy:

private void Awake()
{
// โœ… PERSISTENT LISTENER (Survives scene reload)
// Registered in Awake, cleaned in OnDestroy
onSpamPersistentEvent.AddPersistentListener(OnSpamPersistentLog, priority: -10);
}

private void OnDestroy()
{
// โœ… CLEANUP PERSISTENT
onSpamPersistentEvent.RemovePersistentListener(OnSpamPersistentLog);
}

public void OnSpamPersistentLog()
{
// Empty methodโ€”exists only for Monitor to count
// Simulates background tracking (e.g., analytics, achievements)
}

Monitor Visibility:

  • Listeners Tab: Shows "Persistent Listeners: 1" for OnSpammerPersistent
  • Dashboard: Tracks persistent listener health

๐ŸŽฏ Production Debugging Workflowโ€‹

Scenario 1: Frame Drops During Combatโ€‹

Symptoms:

  • FPS drops from 60 to 30 during combat
  • No obvious Unity Profiler spikes

Debug Steps:

  1. Open Performance Tab
  2. Sort by "Avg Time" (descending)
  3. Look for events with >2ms execution
  4. Click event โ†’ Details Tab โ†’ See caller methods
  5. Optimize heavy listeners or reduce fire frequency

Scenario 2: Event Not Firingโ€‹

Symptoms:

  • UI button click does nothing
  • Expected behavior doesn't occur

Debug Steps:

  1. Open Recent Events Tab
  2. Search for expected event name
  3. If found: Event firing but listeners not responding
    • Go to Listeners Tab โ†’ Check listener count
    • Verify method names match
  4. If not found: Event not being raised
    • Check raiser code's .Raise() call
    • Verify event asset reference in Inspector

Scenario 3: Memory Leak Suspectedโ€‹

Symptoms:

  • Memory usage grows over time
  • GC spikes increase

Debug Steps:

  1. Open Performance Tab
  2. Check "GC Alloc" column
  3. Look for events allocating >0 KB per fire
  4. Click event โ†’ Listeners Tab โ†’ Check for closure allocations
  5. Refactor to avoid per-fire allocations

Scenario 4: Ghost Events (Dead Code)โ€‹

Symptoms:

  • Warning tab shows [No Listeners]

Debug Steps:

  1. Open Warnings Tab
  2. Identify ghost events
  3. Option A: Event is debug-only โ†’ Ignore warning
  4. Option B: Listener registration failed
    • Check OnEnable for AddListener call
    • Verify event asset reference matches
  5. Option C: Dead code โ†’ Remove .Raise() call

๐Ÿ”‘ Monitor Best Practicesโ€‹

โœ… DOโ€‹

During Development:

  • Keep Monitor open in second display
  • Check after adding new events
  • Verify listener counts match expectations
  • Profile before/after optimizations

During Stress Testing:

  • Generate high load (like this demo)
  • Monitor Performance tab for >1ms events
  • Check Warnings tab for integrity issues
  • Export metrics for team review

In Production Builds:

  • Enable Monitor in Development Builds
  • Test on target devices (mobile, console)
  • Profile in realistic scenarios
  • Document performance baselines

โŒ DON'Tโ€‹

Performance Anti-Patterns:

  • Fire events every frame (>60/sec) without batching
  • Allocate memory in listeners (closures, LINQ)
  • Call expensive operations synchronously

Debugging Anti-Patterns:

  • Ignore yellow warnings ("it's just a warning")
  • Rely solely on Debug.Log for event debugging
  • Skip listener cleanup (OnDisable missing)
  • Leave test events in production builds

๐Ÿ“Š Monitor vs Unity Profilerโ€‹

FeatureGame Event MonitorUnity Profiler
FocusEvent system onlyEntire engine
GranularityPer-event metricsPer-method calls
Listener Trackingโœ… Built-inโŒ Manual
Frequency Analysisโœ… Built-inโš ๏ธ Indirect
Flow Visualizationโœ… Automation tabโŒ N/A
Warningsโœ… AutomaticโŒ Manual analysis
Learning CurveEasySteep
Best ForEvent debuggingOverall performance

Recommended Workflow:

  1. Monitor: Identify problematic events
  2. Unity Profiler: Deep-dive into listener methods
  3. Monitor: Verify fixes reduced execution time

๐ŸŽฏ What's Next?โ€‹

You've mastered the complete GameEventSystem workflowโ€”from basic events to enterprise observability. The Examples section is complete!

Next Steps: