Skip to main content

12 Multi Database: Modular Event Architecture

GES ยท Examples

Run a chain whose events are stored in three active databases and verify its archive step.

For teams organizing large event sets and reducing merge conflicts across many contributors.

Overviewโ€‹

The launch flow reads events from separate databases registered with the same manager. Open the manager and the FlowGraph to trace which database owns each step and where the cross-database flow ends.

๐Ÿ”ˆ Hover for sound

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:

Register the databases โ†’ Read events from active databases โ†’ Resolve each FlowGraph node by event GUID

FlowGraph resolves target events from the active databases using their internal GUIDs. Keep the three databases active during this demo so the chain can reach its archive step.


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

Registering Databases at Runtimeโ€‹

Keep shared databases registered across levels. When a level changes, register its database asset with the manager, then unregister the previous level's asset once it is no longer needed.

void SwitchLevelDatabase(GameEventDatabase previousLevelDb, GameEventDatabase currentLevelDb)
{
if (previousLevelDb == currentLevelDb)
return;

var manager = GameEventManager.Instance;
manager.RegisterDatabase(currentLevelDb);
manager.UnregisterDatabase(previousLevelDb);
}

These calls change which databases the manager uses. For on-demand asset loading and release, use Addressables Databases.


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 GameObjectDamageInfoGameEvent 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

The sender calls Raise() on its serialized event asset reference. The receiver methods also work across databases. The manager can look up events by their internal GUID across its registered, active databases.


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)