Skip to main content

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.

๐Ÿ’ก What You'll Learn
  • 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 events
  • GameEventDatabase_Combat.asset - Action & VFX events
  • GameEventDatabase_System.asset - Utility & cleanup events

The Result: Identical runtime behavior, but modular organization for better scalability.


๐Ÿ—‚๏ธ Database Architectureโ€‹

Physical Asset Structureโ€‹

Project Assets

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
๐Ÿ“ฆ Database as Asset

Event databases are ScriptableObjects, meaning they:

  • Exist as .asset files 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) from Core DB
    • Step 3 (Fire) from Combat DB
    • Step 5 (Archive) from System DB

Result: โœ… Seamless cross-database execution


Database Loading Verificationโ€‹

This test proves the modular loading system works:

Step 3: Disable Combat Database

  1. Select Game Event Manager in Hierarchy
  2. Expand Databases list in Inspector
  3. Find GameEventDatabase_Combat entry
  4. 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:

Manager Databases

Databases List (3 entries):

  1. โœ… GameEventDatabase_Core - Active
  2. โœ… GameEventDatabase_Combat - Active
  3. โœ… 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
โšก Zero Performance Cost

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:

Editor Database Dropdown

Database Dropdown (Toolbar): Shows all available databases:

  • GameEventDatabase_Core (selected)
  • GameEventDatabase_Combat
  • GameEventDatabase_System

Workflow:

  1. Select Database: Choose which database to edit
  2. View Events: Editor shows only events from selected database
  3. Create Events: New events go into currently selected database
  4. 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
๐Ÿ”„ Context Switching

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:

Inspector Dropdown

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
๐ŸŽฏ Smart Filtering

The dropdown automatically filters by:

  1. Type compatibility - Only shows events matching field type
  2. Active databases - Only shows events from databases loaded by Manager
  3. 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
๐Ÿ”— GUID-Based References

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

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