I’ve been exploring the Scriptable Object Pattern in Unity and came across an idea for accessing game objects from different scenes in the current scene.
The idea is to have a container ScriptableObject that can store a single reference to an object. MonoBehaviour
instances can register themselves with this container in Awake()
, making them accessible throughout the game.
Here’s what it looks like:
public class ContainerBase<T> : ScriptableObject where T : class
{
private T _ref;
public T Ref => _ref;
public void Occupy(T @ref)
{
if (_ref != null)
{
Debug.LogError($"[{name}] Attempted to register multiple {typeof(T).Name} instances.", this);
return;
}
_ref = @ref;
}
public void Release()
{
_ref = null;
}
}
The problem is making sure a container is always occupied during runtime. My idea is to create global dependencies as prefabs and instantiate them using RuntimeInitializeOnLoad
. These objects register themselves in Awake()
and release in OnDestroy()
.
This avoids having scripts directly reference objects through singletons. I don’t think singletons are evil—they can be really powerful when used correctly—but in team projects, people tend to call them from random places just because they can, and that can turn into a mess. This way, everything depends on the container, making dependencies more structured.
One issue I see is that this doesn’t work well for lazy singletons, where instances are created only when needed.
In personal projects, I usually just go with singletons because they’re simple. But in a team setting, they often lead to spaghetti code. I’m wondering if this approach is worth using or if I should just stick to singletons. Curious to hear what others think!