Skip to main content

MonoSingleton

Important Attention Reminder

Coding Style wiki


MonoSingleton<T> is the MonoBehaviour singleton base class of SingletonSystem (thread-lock protected). When accessing the instance, it first looks for an existing instance in the scene, otherwise automatically creates a GameObject with the component attached; it supports DontDestroyOnLoad cross-scene persistence control and replaces Unity's Awake / Start / OnDestroy with the OnCreate / OnStart / OnRelease lifecycle hooks.

NamespaceOxGKit.SingletonSystem
Typepublic abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
SourceMonoSingleton.cs
using OxGKit.SingletonSystem;

Reminder For pure data or logic manager classes that do not need to live on a GameObject, use NewSingleton instead.

Quick Start

using OxGKit.SingletonSystem;

public class GameManager : MonoSingleton<GameManager>
{
protected override void OnCreate() { /* Call by Unity.Awake */ }

protected override void OnStart() { /* Call by Unity.Start */ }

protected override void OnRelease() { /* Call by Unity.OnDestroy */ }

public void SaveGame() { /* ... */ }
}

// Get and access the instance (find-or-create, DontDestroyOnLoad by default)
GameManager.GetInstance().SaveGame();

// Scene-scoped singleton (destroyed with the scene)
GameManager.GetInstance(dontDestroyOnLoad: false);

// Explicit initialization at boot (warm-up)
GameManager.InitInstance();

// Destroy the instance (GameObject included)
GameManager.DestroyInstance();

General Rules

Lifecycle Mapping

The base class implements Awake(), Start(), and OnDestroy() as private methods and invokes the following hooks guarded by flags:

Unity MethodHookFlag
AwakeOnCreateisCreated
StartOnStartisStarted
OnDestroyOnReleaseisReleased (also resets isCreated, isStarted, and the instance reference)

Important Do not implement Awake(), Start(), or OnDestroy() (occupied by the base class); every other Unity method (Update, OnEnable, etc.) can be implemented normally.

Instance Creation Rules

  1. Scene-placed instance: registers itself as the singleton in Awake, and the dontDestroyOnLoad field on the Inspector decides whether it persists (see Module Intro).
  2. Created from code: when GetInstance is called and no instance exists, it looks for an existing scene instance (FindObjectsOfType, first found wins), otherwise automatically creates a new GameObject(typeof(T).Name) with the component attached.

Attention GetInstance only performs instance creation in Play Mode (Application.isPlaying).

Attention Multiple scene-placed instances of the same type are not automatically deduplicated (the first found wins); avoid placing duplicates across additively-loaded scenes.

Reminder Events registered in OnCreate / OnStart must be unregistered in OnRelease — persistent singletons accumulate stale delegates otherwise. When accessing the singleton from shutdown/teardown paths, check with CheckInstanceExists first to avoid re-creating the instance mid-quit.


Members

MemberDescription
public bool dontDestroyOnLoad(Instance field) Whether to mark the instance with DontDestroyOnLoad in Awake, default true; configurable on the Inspector for scene-placed instances.
public static bool isCreatedWhether OnCreate has been invoked.
public static bool isStartedWhether OnStart has been invoked.
public static bool isReleasedWhether the instance has been destroyed (OnRelease invoked); reset to false when a new instance runs Awake.

Instance Management

Methods Overview

MethodDescription
GetInstanceGets the singleton instance (find-or-create).
InitInstanceInitializes the singleton instance (same as calling GetInstance).
CheckInstanceExistsChecks if an instance exists.
DestroyInstanceDestroys the singleton instance.

GetInstance

public static T GetInstance(bool dontDestroyOnLoad = true)

Gets the singleton instance (thread-lock protected). If no instance exists yet (Play Mode only), it first looks for an existing instance in the scene, otherwise automatically creates a new GameObject(typeof(T).Name) with the component attached; when the dontDestroyOnLoad parameter is true, the instance is marked and DontDestroyOnLoad is applied.

// Cross-scene persistence needed (default)
GameManager.GetInstance();

// No cross-scene persistence needed (set once at the first access)
StageManager.GetInstance(dontDestroyOnLoad: false);

Attention The dontDestroyOnLoad parameter takes effect on the first instance creation — decide it at the first access call site and keep it consistent.

InitInstance

public static void InitInstance(bool dontDestroyOnLoad = true)

Initializes the singleton instance (same as calling GetInstance); suitable for explicitly controlling the creation order during boot (warm-up), avoiding ordering issues caused by lazy creation.

private void Awake()
{
GameManager.InitInstance();
AudioManager.InitInstance();
}

CheckInstanceExists

public static bool CheckInstanceExists()

Checks if an instance exists (does not trigger creation).

if (GameManager.CheckInstanceExists())
GameManager.GetInstance().SaveGame();

DestroyInstance

public static void DestroyInstance(bool gameObjectIncluded = true)

Destroys the singleton instance; when gameObjectIncluded is true, the GameObject is destroyed as well, when false, only the component itself is destroyed. Destruction triggers OnRelease and resets the state flags and the instance reference, after which a new instance can be created again.

// Destroy the GameObject as well (default)
GameManager.DestroyInstance();

// Destroy the component only (keep the GameObject)
GameManager.DestroyInstance(gameObjectIncluded: false);

Lifecycle Hooks

Methods Overview

MethodDescription
OnCreateInvoked by Unity Awake.
OnStartInvoked by Unity Start.
OnReleaseInvoked by Unity OnDestroy.

OnCreate

protected abstract void OnCreate()

Invoked by Unity Awake (guarded by the isCreated flag to fire only once); implement initialization logic here.

OnStart

protected abstract void OnStart()

Invoked by Unity Start (guarded by the isStarted flag to fire only once); implement startup logic here.

OnRelease

protected abstract void OnRelease()

Invoked by Unity OnDestroy; implement release logic here (unregister events, release resources). Afterwards isReleased becomes true, and isCreated, isStarted, and the instance reference are reset.