12 Multi Database: Modular Event Architecture
๐ Overviewโ
In large-scale projects with hundreds of events (RPGs, MMOs, complex simulations), storing all events in a single monolithic database asset becomes a maintenance nightmareโslow Editor performance, Git merge conflicts, and poor organization. The Multi-Database System solves this by allowing you to split events across multiple modular ScriptableObject assets (e.g., Core_DB, Combat_DB, UI_DB), each managed independently.
- How to create and manage multiple event databases
- How the Manager merges databases at runtime with zero performance cost
- How Flow Graphs seamlessly connect events across different databases
- Organizational strategies for team collaboration and version control
๐ฌ Demo Sceneโ
Assets/TinyGiants/GameEventSystem/Demo/12_MultiDatabase/12_MultiDatabase.unity
What This Demo Demonstratesโ
This demo reuses the exact Chain Event logic from Demo 11 (the 5-step Launch Protocol), but with a critical architectural difference:
Demo 11: All 6 events stored in GameEventDatabase_Chain.asset (single file)
Demo 12: Same 6 events distributed across 3 separate database files:
GameEventDatabase_Core.asset- Logic flow eventsGameEventDatabase_Combat.asset- Action & VFX eventsGameEventDatabase_System.asset- Utility & cleanup events
The Result: Identical runtime behavior, but modular organization for better scalability.
๐๏ธ Database Architectureโ
Physical Asset Structureโ

In Project Window:
๐ 12_MultiDatabase/
โ
โโโ ๐ง GameEventDatabase_Core.asset โ [ ๐ฆ 2 Events ]
โ โโโ ๐ฌ 0_StartSequence โ Intro logic
โ โโโ โ๏ธ 1_SystemCheck โ Initialization
โ
โโโ โ๏ธ GameEventDatabase_Combat.asset โ [ ๐ฆ 2 Events ]
โ โโโ โก 2_Charge โ Skill initiation
โ โโโ ๐ฅ 3_Fire โ Projectile logic
โ
โโโ ๐ ๏ธ GameEventDatabase_System.asset โ [ ๐ฆ 2 Events ]
โ โโโ โณ 4_CoolDown โ Global timers
โ โโโ ๐ 5_Archive โ Persistence/Save
โ
โโโ ๐ธ๏ธ GameEventFlow_MultiDatabase.asset โ [ ๐ Flow Graph ]
โโ (Connects events across all databases listed above)
Key Observation:
Each database is a ScriptableObject assetโa physical .asset file in your project. You can:
- Move them to different folders
- Assign them to different team members (no merge conflicts!)
- Load/unload them dynamically at runtime
- Version control them independently
Event databases are ScriptableObjects, meaning they:
- Exist as
.assetfiles in your project - Can be referenced in scenes
- Survive domain reloads
- Are serialized independently
This is fundamentally different from systems that store events in a single JSON config or embedded in scenes.
๐ฎ How to Interactโ
Runtime Behavior Testโ
The scene is visually identical to Demo 11. Same turrets, same buttons, same launch sequence.
Step 1: Enter Play Mode
Step 2: Test Normal Launch
- Click "Launch A"
- Observe: Full 5-step sequence executes perfectly
- System Check โ Charge (1s delay) โ Fire โ CoolDown โ Archive
- Behind the Scenes: Execution jumps across 3 databases:
- Step 1 (
SystemCheck) fromCoreDB - Step 3 (
Fire) fromCombatDB - Step 5 (
Archive) fromSystemDB
- Step 1 (
Result: โ Seamless cross-database execution
Database Loading Verificationโ
This test proves the modular loading system works:
Step 3: Disable Combat Database
- Select Game Event Manager in Hierarchy
- Expand Databases list in Inspector
- Find
GameEventDatabase_Combatentry - Uncheck the "Active" toggle
Step 4: Test Disabled Database
- Click "Launch A"
- Result: โ Sequence hangs at Step 2 (Charge)
- Console shows errors about missing events
- Steps 3-5 never execute
Step 5: Re-Enable Combat Database
- Check the "Active" toggle again
- Click "Launch A"
- Result: โ Sequence works again
What This Proves:
- Databases can be dynamically enabled/disabled at runtime
- Missing databases break execution (as expected)
- No "auto-reload" magicโyou control what's loaded
๐๏ธ Multi-Database Configurationโ
Runtime: Manager Setupโ
Select Game Event Manager in Hierarchy to see the multi-database configuration:

Databases List (3 entries):
- โ
GameEventDatabase_Core- Active - โ
GameEventDatabase_Combat- Active - โ
GameEventDatabase_System- Active
How Runtime Merging Works:
๐ System Initiation
โ
โโโ ๐ Stage 1: Discovery
โ โโโ ๐ Manager scans & reads all Active Databases
โ
โโโ ๐งฉ Stage 2: Consolidation
โ โโโ ๐ ๏ธ Merges all events into a Global Lookup Table (LUT)
โ โโโ ๐งฌ Key: Event GUID (Unique Identifier)
โ โโโ ๐ฆ Value: Event Reference (Direct Pointer)
โ
โโโ ๐ Stage 3: Linking
โโโ ๐ธ๏ธ FlowGraph references resolved via GUID
Performance Characteristics:
- Lookup Speed: O(1) - same as single database
- Memory Overhead: Negligible (just dictionary pointers)
- Initialization: Databases merged once at startup
- Runtime Cost: None - already merged
Having 1 database or 100 databases makes no runtime difference. The Manager merges them into a single lookup table at startup. Choose database count based on organization needs, not performance concerns.
Design Time: Editor Database Switchingโ
Open Game Event Editor to manage events across databases:

Database Dropdown (Toolbar): Shows all available databases:
GameEventDatabase_Core(selected)GameEventDatabase_CombatGameEventDatabase_System
Workflow:
- Select Database: Choose which database to edit
- View Events: Editor shows only events from selected database
- Create Events: New events go into currently selected database
- Switch Context: Dropdown allows quick navigation
Example - Viewing Core Database:
- Dropdown:
GameEventDatabase_Core - Events Shown:
0_StartSequence,1_SystemCheck(2 total) - Events Hidden: All events from other databases
Example - Viewing Combat Database:
- Dropdown:
GameEventDatabase_Combat - Events Shown:
2_Charge,3_Fire(2 total) - Events Hidden: All events from other databases
The Editor shows one database at a time to reduce visual clutter. Use the dropdown to switch between databases. This doesn't affect runtimeโall active databases are still merged.
Inspector: Cross-Database Event Selectionโ
When assigning events to scripts in Inspector, the GameEventDropdown shows events from all active databases:

Dropdown Structure: Events grouped by database and category:
โ๏ธ GameEventDatabase_Combat / Default
โโ โก 2_Charge
โโ โก 3_Fire
๐ง GameEventDatabase_Core / Default
โโ ๐ ๐ฌ 0_StartSequence โ [ CURRENTLY SELECTED ]
โโ โ๏ธ 1_SystemCheck
๐ ๏ธ GameEventDatabase_System / Default
โโ โณ 4_CoolDown
โโ ๐พ 5_Archive
Key Behaviors:
- All Active Databases: Dropdown includes events from every database loaded by Manager
- Database Labels: Events prefixed with database name for clarity
- Category Grouping: Events organized by category within each database
- Type Filtering: Only shows events matching field's type signature
Example Assignment:
[GameEventDropdown]
public GameEvent<GameObject, DamageInfo> sequenceStartEvent;
Dropdown shows:
- โ
0_StartSequence(from Core DB) - Compatible type - โ Other events hidden if type doesn't match
The dropdown automatically filters by:
- Type compatibility - Only shows events matching field type
- Active databases - Only shows events from databases loaded by Manager
- Database/Category - Groups for easy navigation
This prevents type errors and makes large projects navigable.
๐ Multi-Database Benefitsโ
Team Collaborationโ
Problem: 10 developers all editing GlobalDatabase.asset
- Constant Git merge conflicts
- Long Editor freezes when loading
- Unclear ownership
Solution: Module-based database ownership
๐ Databases/
โ
โโโ ๐ง Core_DB.asset โ ๐ป [ Owner: Lead Programmer ]
โ โโ Global states, initialization, & low-level triggers.
โ
โโโ โ๏ธ Combat_DB.asset โ ๐คบ [ Owner: Combat Team ]
โ โโ Attack sequences, AI behaviors, & damage logic.
โ
โโโ ๐ฅ๏ธ UI_DB.asset โ ๐จ [ Owner: UI Team ]
โ โโ Menu transitions, HUD updates, & button feedback.
โ
โโโ ๐ Audio_DB.asset โ ๐ง [ Owner: Audio Team ]
โ โโ Ambient loops, SFX triggers, & music state switches.
โ
โโโ ๐บ๏ธ Level1_DB.asset โ ๐ [ Owner: Level Designer A ]
โ โโ Puzzles, triggers, and events specific to Level 1.
โ
โโโ ๐บ๏ธ Level2_DB.asset โ ๐ [ Owner: Level Designer B ]
โโ Puzzles, triggers, and events specific to Level 2.
Result:
- โ Parallel work without conflicts
- โ Clear module ownership
- โ Faster Git operations (smaller diffs)
- โ Easier code reviews (smaller changesets)
Logical Organizationโ
Problem: 500 events in one database
- Hard to find specific events
- No clear boundaries between systems
- Difficult to understand dependencies
Solution: Domain-driven database design
โ๏ธ Combat_DB โ [ 50 Events ]
โโ Attack, defense, & high-frequency damage logic.
๐ Movement_DB โ [ 30 Events ]
โโ Walk, jump, dash, & physics-based state changes.
๐ Inventory_DB โ [ 80 Events ]
โโ Pick up, use, drop, & item-durability mechanics.
๐ Quest_DB โ [ 100 Events ]
โโ Start, progress, & complex completion milestones.
๐ฅ๏ธ UI_DB โ [ 70 Events ]
โโ Menu transitions, HUD updates, & dialog systems.
๐ Audio_DB โ [ 40 Events ]
โโ Dynamic music layers & localized SFX triggers.
๐บ๏ธ Level_Specific_DB โ [ 130 Events ]
โโ Per-level unique environmental & puzzle events.
Result:
- โ Clear conceptual boundaries
- โ Easy to locate relevant events
- โ Understandable dependencies
- โ Modular testing (load only needed DBs)
Dynamic Loadingโ
Use Case: Mobile game with multiple levels
Problem: Loading all 1000 events at startup wastes memory
Solution: Runtime database management
void LoadLevel(int levelIndex)
{
// Unload previous level's events
manager.UnloadDatabase("Level" + (levelIndex - 1));
// Load current level's events
manager.LoadDatabase("Level" + levelIndex);
// Keep core systems always loaded
// (Core_DB, Combat_DB, UI_DB remain active)
}
Result:
- โ Lower memory footprint
- โ Faster level transitions
- โ Better performance on low-end devices
- โ Modular content updates (patch single DB)
๐ ๏ธ Code Architectureโ
Location-Agnostic Codeโ
The code for Demo 12 is identical to Demo 11. Scripts don't know or care which database an event lives in:
MultidatabaseRaiser.cs:
[GameEventDropdown]
public GameEvent<GameObject, DamageInfo> sequenceStartEvent;
public void RequestLaunchA()
{
// Works regardless of which database contains this event
// Could be Core_DB, Combat_DB, or any other database
sequenceStartEvent.Raise(turretA, info);
}
MultidatabaseReceiver.cs:
// Methods bound to events from different databases
public void OnSystemCheck(GameObject sender, DamageInfo args) // Core_DB
public void OnStartCharging(GameObject sender, DamageInfo args) // Combat_DB
public void OnFireWeapon(GameObject sender, DamageInfo args) // Combat_DB
public void OnCoolDown(GameObject sender, DamageInfo args) // System_DB
public void OnSequenceArchived(GameObject sender, DamageInfo args) // System_DB
Key Insight: Scripts reference events by GUID (stored in serialized field), not by database path. The Manager resolves GUIDs to event instances at runtime, regardless of which database contains them.
Flow Graph Cross-Database Connectionsโ
The Flow Graph connects events from different databases seamlessly:
Visual Flow (Same as Demo 11):
๐ง [ Core_DB ] โ The Initiation Layer
โ โโ ๐ฌ 0_StartSequence โ ๐ Root (The Ignition)
โ โโ โ๏ธ 1_SystemCheck โ ๐ก๏ธ Condition (The Guard)
โ
โผ (Signal Handover)
โ
โ๏ธ [ Combat_DB ] โ The Action Layer
โ โโ โก 2_Charge โ โฑ๏ธ Delay (The Preparation)
โ โโ ๐ฅ 3_Fire โ ๐ Action (The Execution)
โ
โผ (Signal Handover)
โ
๐ ๏ธ [ System_DB ] โ The Maintenance Layer
โ โโ โณ 4_CoolDown โ โ Wait (The Recovery)
โ โโ ๐พ 5_Archive โ ๐งน Filter (The Cleanup)
Behind the Scenes:
- Each node stores the event's GUID
- Manager resolves GUID to actual event at runtime
- Connections work even if events move between databases
- No "link breaking" when reorganizing
Events are referenced by immutable GUIDs, not file paths. You can:
- Move events between databases
- Rename database files
- Reorganize folder structure
and all references remain valid as long as the event's GUID doesn't change.
๐ Best Practicesโ
When to Create Multiple Databasesโ
Good Reasons:
- โ Team Ownership - Different teams work on different systems
- โ Logical Domains - Clear conceptual boundaries (Combat, UI, Audio)
- โ Dynamic Loading - Load/unload events per level or mode
- โ Version Control - Reduce merge conflicts
- โ Testing - Load only relevant databases for specific tests
Bad Reasons:
- โ Performance - Multi-DB has zero runtime cost, so don't split for speed
- โ Event Count - 50 events in one DB is fine, don't over-split
- โ Premature Optimization - Start with one DB, split when you feel pain
Recommended Database Structureโ
Small Project (< 100 events):
๐ Databases/
โโ ๐ง GameEventDatabase_Main.asset โ [ ๐ฆ All-in-One ]
โโ (All Combat, UI, and System events reside here)
Medium Project (100-300 events):
๐ Databases/
โโ ๐ง Core_DB.asset โ [ โ๏ธ Fundamental Systems ]
โโ ๐ฎ Gameplay_DB.asset โ [ โ๏ธ Main Mechanics ]
โโ ๐ฅ๏ธ UI_DB.asset โ [ ๐จ Menus & HUD ]
Large Project (300+ events):
๐ Databases/
โโ ๐ง Core_DB.asset โ ๐ป [ Global Systems ]
โโ โ๏ธ Combat_DB.asset โ ๐คบ [ Battle Mechanics ]
โโ ๐ Movement_DB.asset โ ๐คธ [ Character Locomotion ]
โโ ๐ Inventory_DB.asset โ ๐ฆ [ Item & Grid Management ]
โโ ๐ Quest_DB.asset โ ๐ [ Mission & Story Logic ]
โโ ๐ฅ๏ธ UI_DB.asset โ ๐จ [ Global Interface ]
โโ ๐ Audio_DB.asset โ ๐ง [ Dynamic Soundscape ]
โ
โโ ๐บ๏ธ Level_Specific/ โ ๐ [ Per-Level Unique Events ]
โโ Level_01_DB.asset
โโ Level_02_DB.asset
โโ ...
Naming Conventionsโ
Database Files:
GameEventDatabase_[Module].asset(required prefix for Editor tools)- Examples:
GameEventDatabase_Combat.asset,GameEventDatabase_UI.asset
Event Names:
- Prefix with step/priority:
0_StartSequence,1_SystemCheck - Or prefix with module:
Combat_AttackStart,UI_MenuOpen - Avoid generic names:
Event1,MyEvent(hard to search)
๐ฏ What's Next?โ
You've learned how to organize events across multiple databases for better scalability and collaboration. Next, let's explore runtime API usage.
Next Chapter: See runtime event manipulation in 13 Runtime API
๐ Related Documentationโ
- Game Event Manager - Database loading and management
- Game Event Editor - Multi-database editing workflows
- Best Practices - Organizational patterns for large projects