A Generic Singleton
Part of the Game Architecture in Unity section of Coddy's Unity journey. Lesson 34 of 50.
Section 3's singleton is five lines that every manager repeats: a static Instance, an Awake that sets it, the duplicate check. A generic base class writes them once. Each manager derives from it, naming itself as the type:
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
public static T Instance { get; private set; }
protected virtual void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this as T;
}
}
public class ScoreManager : Singleton<ScoreManager>
{
public int score;
public void Add(int points) { score += points; }
}
public class SoundManager : Singleton<SoundManager>
{
public void Play(string clip) { Debug.Log("Playing " + clip); }
}// in any script
ScoreManager.Instance.Add(10);
SoundManager.Instance.Play("coin");A static member of a generic class belongs to each type made from it: Singleton<ScoreManager> and Singleton<SoundManager> are two types with an Instance each, so the managers never share one. ScoreManager.Instance is already typed ScoreManager, which is what T is for. Inside the base, this is only known as a Singleton<T>, so this as T hands it over as the manager it really is.
The base is abstract: Unity puts only the managers on objects. A manager that needs Awake of its own must not write a plain void Awake(). That hides the base's method (the compiler warns about it), Unity calls only the manager's, and Instance is never set. Override it and call the base first:
protected override void Awake()
{
base.Awake();
score = 0;
}Challenge
MediumA town and a forest, joined by purple portals. Each scene has its own Wallet and MusicPlayer object, so either one plays on its own, and the coins call Wallet.Instance.Add(1). Today each manager is section 3's singleton, so every load replaces the wallet with an empty one. Give both managers a generic base that keeps them through scene loads:
- In
PersistentSingleton.cs, writepublic abstract class PersistentSingleton<T>, a MonoBehaviour for any MonoBehaviour type T, with a public staticInstanceof type T that only the class sets, and aprotected virtual void Awake(). - Its Awake keeps the first of its kind: that one becomes Instance and survives scene loads. Any later one destroys its own object and changes nothing.
WalletandMusicPlayerderive from it, and their ownInstancefields go.MusicPlayerkeeps an Awake of its own that logsNow playing: Adventure. It must run after the base's Awake, and only for the one that stays, so the music starts once per game.
The arrows walk the Player. Press Play, pick up the coin, go to the forest and back, then Check.
Try it yourself
using UnityEngine;
// PersistentSingleton<T>: one instance that lasts through scene loads
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Game Architecture in Unity
1Components, Not Hierarchies
Small ComponentsA Base Enemy ScriptAbstract ComponentsComponents Working TogetherRecap: Modular Turret10Project: Arena Survivor
The HeroEnemy Types