Skip to content

Instantly share code, notes, and snippets.

@DraperDanMan
Last active November 9, 2021 11:07
Show Gist options
  • Select an option

  • Save DraperDanMan/512c4869af5e3f6ea6d61aab1a5e4fb2 to your computer and use it in GitHub Desktop.

Select an option

Save DraperDanMan/512c4869af5e3f6ea6d61aab1a5e4fb2 to your computer and use it in GitHub Desktop.
Safer Unity Singleton Baseclass
using System.Runtime.CompilerServices;
using UnityEngine;
/// <summary>
/// A generic Singleton Monobehaviour will all the safety systems already set up.
/// </summary>
/// <typeparam name="BehaviourType">This is generally going to be your class name that will become the singleton.</typeparam>
public abstract class SingletonBehaviour<BehaviourType> : MonoBehaviour where BehaviourType : class
{
public static BehaviourType Instance
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
private set;
}
public bool IsInitialized { get; private set; }
private bool _isDuplicate;
/// <summary>
/// The Awake method for this singleton. All your Awaking should be done in Initialize and/or OnEnable
/// </summary>
protected virtual void Awake()
{
if (Instance != null)
{
_isDuplicate = true;
Destroy(gameObject);
Debug.LogError("Multiple instances of " + typeof(BehaviourType).ToString() + " detected", this);
return;
}
else
{
Instance = this as BehaviourType;
if (Instance == null)
Debug.LogError("SingletonBehaviour could not cast to " + typeof(BehaviourType), this);
UnityEngine.Profiling.Profiler.BeginSample(Instance.GetType().Name + ".Initialize");
Initialize();
UnityEngine.Profiling.Profiler.EndSample();
IsInitialized = true;
}
}
/// <summary>
/// Safely Handles the shutdown of the Singleton if it is destroyed from somewhere.
/// </summary>
protected void OnDestroy()
{
if (!_isDuplicate)
{
Instance = null;
Shutdown();
IsInitialized = false;
}
_isDuplicate = false;
}
/// <summary>
/// Replaces the Awake function of the singleton and is called only when it is safe to do so (i.e, Not a duplicate.)
/// </summary>
protected abstract void Initialize();
/// <summary>
/// Called when the Single is being shutdown (If you ever expect it to die. Like the player perhaps?)
/// </summary>
protected abstract void Shutdown();
}
@DraperDanMan
Copy link
Author

DraperDanMan commented Nov 9, 2021

Usage Example:

public class LoadingScreen : SingletonBehaviour<LoadingScreen>
{
    protected override void Initialize()
    {
        //replaces Awake()
    }

    protected override void Shutdown()
    {
        //Cleanup and replaces OnDestroy()
    }
}

The behaviour here is to protect from accidental duplicated singletons in unity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment