Scene-Safe Singleton GameManager in Unity
When creating a GameManager that needs to be accessed globally, it's common to use the Singleton pattern. However, if your project has more than one scene, you’ll often face the issue of having to manually place a GameManager GameObject in every scene.
To solve this cleanly, you can extend the basic singleton setup for scene-safe behavior.
Singleton Pattern That Survives Scene Changes
public class GameManager : MonoBehaviour
{
public static GameManager Instance { get; private set; }
void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject); // Remove duplicate
return;
}
Instance = this;
DontDestroyOnLoad(gameObject); // Persist across scenes
}
}
This setup ensures:
- The GameManager is created only once in the first scene.
- It persists across scenes using
DontDestroyOnLoad
. - Duplicates in later scenes are destroyed immediately.
However, problems arise when a scene without the GameManager is launched directly (e.g., testing a subscene alone). In such cases, GameManager
doesn’t exist, which can lead to NullReferenceException
.
Auto-Creating GameManager Using the Resources Folder
To avoid the null reference issue, you can store a GameManager prefab inside the Resources
folder and have it load automatically when needed.
Steps to Create the Prefab
- Create a GameManager GameObject in the Hierarchy.
- Drag it into
Assets/Resources
to save it as a prefab. - Then delete the GameManager from the Hierarchy.
Add Auto-Loading Code to GameManager.cs
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void AutoCreateSingleton()
{
if (Instance == null)
{
GameObject prefab = Resources.Load<GameObject>("GameManager");
if (prefab != null)
{
_ = Instantiate(prefab);
}
else
{
Debug.LogError("GameManager prefab not found in Resources folder.");
}
}
}
Note: What is [RuntimeInitializeOnLoadMethod]
?
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
tells Unity to automatically call the static method right below it before any scene is loaded.
This method must be declared as static
, and it will be executed even if there is no GameObject in the scene.
Now, the GameManager will automatically be created if it doesn't exist, keeping your scenes safe from null reference errors.
Summary
- Basic singleton is fine for single-scene projects.
- For multi-scene setups, use
DontDestroyOnLoad
and duplicate checks. - To avoid errors in isolated scenes, auto-load the GameManager from
Resources
. - This structure becomes especially useful as your project grows in size and complexity.
Additionally...
If your singleton class, such as GameManager
, needs to initialize data specific to each scene,
you should not rely on Awake()
or Start()
methods.
These methods are only called once, and will not be invoked again when the scene is reloaded.
In such cases, you must use the SceneManager.sceneLoaded
event to set up the necessary data whenever a scene changes.
We’ll cover SceneManager.sceneLoaded in more detail in a future post.