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.
- 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:
OnSpammerfires >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)
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.

Metric Cards (Top Row):
| Card | Meaning | Expected Value |
|---|---|---|
| Total Events | Loaded event count | 9 |
| Total Logs | Cumulative fires since play start | 500+ (climbing) |
| Monitored | Events with active performance tracking | 4-6 |
| Warnings | Current active issues | 2+ (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
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

Columns:
| Column | Meaning | Healthy Range |
|---|---|---|
| Event Name | Event identifier | - |
| Avg Time | Average execution ms | <1ms ๐ข |
| Min Time | Fastest execution | - |
| Max Time | Slowest execution | <5ms ๐ก, >5ms ๐ด |
| Listeners | Avg listener count per fire | - |
| GC Alloc | Garbage generated per fire | 0 KB ideal |
Color Coding:
- ๐ข Green: 0-1ms (excellent)
- ๐ก Yellow: 1-5ms (monitor)
- ๐ด Red: >5ms (investigate)
Test Results (Unit B):
- Locate
OnHeavyLoadevent in table - Avg Time: Shows ~6.00ms (๐ก Yellow)
- Max Time: May show ~12.00ms if clicked multiple times (๐ด Red)
- 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
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

Columns:
| Column | Meaning | Example |
|---|---|---|
| Frame | Unity frame number | F:1450 |
| Time | Timestamp since play start | 12.45s |
| Event | Event name | OnHeavyLoad |
| Arguments | Payload preview | <DamageInfo: 100> |
| Caller | Method 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
OnSpammerentries (60+/sec) - Unit C: Sequential pattern:
OnChainStartโ (delay) โOnChainProcessโOnChainFinishโOnTriggerComplete - Unit D: Single
OnGhostentry
Usage:
- Verify event firing order (sequential vs parallel)
- Debug unexpected event triggers
- Investigate caller methods (who's raising this?)
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

Columns:
| Column | Meaning | Healthy Range |
|---|---|---|
| Event Name | Event identifier | - |
| Trigger Count | Total fires since play start | - |
| Freq/sec | Fires per second | <10 ๐ข, 10-30 ๐ก, >30 ๐ด |
| Avg Interval | Time between fires (ms) | >100ms ideal |
| Last Trigger | Time since last fire | - |
Test Results (Unit A):
- Locate
OnSpammerevent - Trigger Count: Rapidly climbing (1000+ after 10sec)
- Freq/sec: Shows >60/s (๐ด Red warning)
- 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
- >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

Severity Levels:
| Icon | Level | Meaning |
|---|---|---|
| ๐ต | Info | Advisory notice (FYI) |
| ๐ก | Warning | Non-critical issue (monitor) |
| ๐ด | Critical | Severe problem (fix immediately) |
Warning Types:
| Warning | Trigger | Severity |
|---|---|---|
[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)
[No Listeners] warnings are usually bugsโeither:
- Listener registration failed (check
OnEnable) - Event asset reference is wrong
- Dead code (remove the
.Raise()call)
Tab 6: ๐ Listeners (Subscription Inspector)โ
Focus: Granular breakdown of WHO is listening

Select an event (e.g., OnHeavyLoad) to see detailed breakdown:
Listener Categories:
| Category | Meaning | Icon |
|---|---|---|
| Basic | Standard AddListener | ๐ |
| Priority | AddPriorityListener with priority value | ๐ข |
| Conditional | AddConditionalListener with predicate | โ |
| Persistent | AddPersistentListener (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 Bindings: Configured in Behavior window
- API Bindings: Registered via
AddListenerin code - Both show up hereโvalidates your hybrid approach
Tab 7: ๐ Automation (Programmatic Flow Visualization)โ
Focus: Visualize code-built Trigger/Chain graphs

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:
| Badge | Meaning |
|---|---|
โฑ๏ธ 0.5s | Delay 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
- 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

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:

| Category | Event Name | Type | Purpose |
|---|---|---|---|
| Unit A | OnSpammer | GameEvent | High-frequency spam |
| Unit A | OnSpammerPersistent | GameEvent | Persistent spam |
| Unit B | OnHeavyLoad | GameEvent<GameObject, DamageInfo> | Performance test |
| Unit B | OnHeavyLoadCondition | GameEvent<GameObject, DamageInfo> | Conditional test |
| Unit C | OnChainStart | GameEvent<DamageInfo> | Root (gold) |
| Unit C | OnChainProcess | GameEvent<DamageInfo> | Chain step 1 |
| Unit C | OnChainFinish | GameEvent<DamageInfo> | Chain step 2 |
| Unit C | OnTriggerComplete | GameEvent | Chain step 3 (trigger) |
| Unit D | OnGhost | GameEvent | Integrity test |
Flow Graph Configurationโ
Programmatic chain built in code:

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)โ

Unit A: Frequency Test
On Spam Event: OnSpammerOn Spam Persistent Event: OnSpammerPersistent
Unit B: Performance Test
On Heavy Load Event: OnHeavyLoadOn Heavy Load Condition Event: OnHeavyLoadCondition
Unit C: Automation Test (Roots)
On Chain Start: OnChainStart
Unit C: Automation Test (Targets)
On Chain Process: OnChainProcessOn Chain Finish: OnChainFinishOn Trigger Complete: OnTriggerComplete
Unit D: Integrity Test
On Ghost Event: OnGhost
Receiver Setup (RuntimeMonitorReceiver)โ

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:
- Open Performance Tab
- Sort by "Avg Time" (descending)
- Look for events with >2ms execution
- Click event โ Details Tab โ See caller methods
- 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:
- Open Recent Events Tab
- Search for expected event name
- If found: Event firing but listeners not responding
- Go to Listeners Tab โ Check listener count
- Verify method names match
- If not found: Event not being raised
- Check raiser code's
.Raise()call - Verify event asset reference in Inspector
- Check raiser code's
Scenario 3: Memory Leak Suspectedโ
Symptoms:
- Memory usage grows over time
- GC spikes increase
Debug Steps:
- Open Performance Tab
- Check "GC Alloc" column
- Look for events allocating >0 KB per fire
- Click event โ Listeners Tab โ Check for closure allocations
- Refactor to avoid per-fire allocations
Scenario 4: Ghost Events (Dead Code)โ
Symptoms:
- Warning tab shows
[No Listeners]
Debug Steps:
- Open Warnings Tab
- Identify ghost events
- Option A: Event is debug-only โ Ignore warning
- Option B: Listener registration failed
- Check
OnEnableforAddListenercall - Verify event asset reference matches
- Check
- 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.Logfor event debugging - Skip listener cleanup (
OnDisablemissing) - Leave test events in production builds
๐ Monitor vs Unity Profilerโ
| Feature | Game Event Monitor | Unity Profiler |
|---|---|---|
| Focus | Event system only | Entire engine |
| Granularity | Per-event metrics | Per-method calls |
| Listener Tracking | โ Built-in | โ Manual |
| Frequency Analysis | โ Built-in | โ ๏ธ Indirect |
| Flow Visualization | โ Automation tab | โ N/A |
| Warnings | โ Automatic | โ Manual analysis |
| Learning Curve | Easy | Steep |
| Best For | Event debugging | Overall performance |
Recommended Workflow:
- Monitor: Identify problematic events
- Unity Profiler: Deep-dive into listener methods
- 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:
- Explore Tools & Support for advanced features
- Review Best Practices for production patterns
- Check Community & Support for help
๐ Related Documentationโ
- Runtime Monitor Tool - Complete Monitor documentation
- Best Practices - Performance optimization patterns
- Programmatic Flow - Building graphs in code
- API Reference - Complete method signatures