Creating ScriptableObject Runtime Sets for Object Tracking
In this lesson, you will learn how to create a ScriptableObject that acts as a central registry, allowing disparate objects in your game to track and access each other without direct scene dependencies.
The Problem: Tight Coupling
In complex games, you often need to find all active enemies, collectables, or NPCs. If an "Achievement Manager" or "UI Tracker" searches the scene using FindObjectsOfType<T>(), you create a rigid dependency that is slow and breaks if objects change scenes or hierarchy. We need a way for objects to "announce" their presence to a shared container.
The Solution: Runtime Sets
A RuntimeSet is a ScriptableObject that holds a List<T> of active objects. Instead of a manager searching for them, the objects themselves register their existence during OnEnable and unregister during OnDisable.
using System.Collections.Generic;
using UnityEngine;
public abstract class RuntimeSet<T> : ScriptableObject
{
public List<T> Items = new List<T>();
public void Add(T item) => Items.Add(item);
public void Remove(T item) => Items.Remove(item);
}
By creating a concrete implementation (e.g., EnemySet : RuntimeSet<Enemy>), you can reference this asset in any component. When an Enemy spawns, it calls enemySet.Add(this). Now, any system—like a "Wave Controller"—can simply access enemySet.Items to see exactly which enemies are currently in the game.
Why This Architecture Matters
- Zero Scene Dependency: The manager doesn't care where the enemies are or how they were spawned; it only cares that they exist in the set.
- Persistence: Since the
RuntimeSetis an asset, it persists across scene loads, making it perfect for tracking objects that travel between levels. - Performance: You avoid the heavy cost of searching the scene hierarchy every frame, replacing it with a simple, cached list lookup.
This pattern transforms your game from a collection of "hidden" scene-dependent references into a clean, decoupled ecosystem where objects manage their own lifecycle participation.
Key Takeaway: Use ScriptableObject Runtime Sets to enable objects to self-register into a shared, global list, eliminating the need for expensive and fragile scene-searching logic.