U
11 / 22 · 9 min
FAQ

Singletons: one GameManager the whole game can reach

the short answer

What is a singleton, and how should a GameManager be written?

A singleton is one live object with a static field pointing at it, so any script can call GameManager.Instance without holding a reference. Set that field in Awake, read it in Start, destroy the second copy a scene reload brings in, and only call DontDestroyOnLoad when the manager really has to outlive the scene.

A score needs to go up from the enemy that died, the pause menu and the save file. None of them owns the manager that holds it. A singleton is the usual answer: one object, one static field pointing at it, and every script can reach it by name.

The pattern, in full

GameManager.cs — a singleton that survives a scene change
using UnityEngine;

public class GameManager : MonoBehaviour
{
    // The one field the rest of the game reaches it through.
    public static GameManager Instance { get; private set; }

    public int Score { get; private set; }

    void Awake()
    {
        // Coming back to a scene that already contains one? This is the spare copy.
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }

        Instance = this;

        // Only for a manager that must outlive the scene. Leave it out otherwise.
        DontDestroyOnLoad(gameObject);
    }

    void OnDestroy()
    {
        // Do not leave the static field pointing at a destroyed object.
        if (Instance == this) Instance = null;
    }

    public void AddScore(int points) => Score += points;
}

Anywhere else in the game, that is now one line: GameManager.Instance.AddScore(10). No public field to drag in the Inspector, no searching the scene for the object.

The four rules that keep it working

  • Assign Instance in Awake, read it in Start. Unity runs every Awake in the scene before the first Start, so a script that reads the manager in Start always finds it. Two scripts reading each other in Awake is a race you cannot win.

  • Destroy the duplicate, not the original. Loading the menu and coming back builds a second manager; the copy that arrives later is the one that has to go, or every reference already handed out points at a dead object.

  • DontDestroyOnLoad only works on a root object. On a child, Unity ignores it and logs a warning — and the manager dies with the scene anyway.

  • Do not mark it DontDestroyOnLoad out of habit. If the manager belongs to one scene, let it die with that scene: a manager that outlives the level it was counting is the source of scores that carry over and enemies counted twice.

One trap in the editor

If you turn off Domain Reload to enter Play Mode faster, static fields keep whatever they held when you last stopped — so Instance still points at an object from the previous session, and the first frame throws. Reset it explicitly, and the shortcut stays safe.

GameManager.cs — two lines that make Play Mode without a domain reload safe
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    static void ResetStatics() => Instance = null;

When not to reach for one

  • Anything that can exist twice — a player in a split screen, an enemy, a weapon — is not a singleton, and forcing it to be one is a rewrite waiting to happen.

  • When only one script needs the manager, a public field dragged in the Inspector is simpler, and the Inspector then shows you what is connected to what.

  • Managers that reach into each other through Instance end up impossible to test or reuse. Two or three in a project is normal; a dozen means the game has no structure left.

the lesson that builds this

Screens, panels and the GameManager

This post is a standalone recipe. In the course, the same thing is built as part of the one project that runs through all five tabs — Basics, lesson 10.