Skip to main content
deleted 3 characters in body
Source Link
aBertrand
  • 176
  • 1
  • 3
  • It doesn't use FindObjectsOfType which is a performance killer

  • It's flexible in that it doesn't need to create a new empty gameobject during the game. You simply add it in the editor (or during the game) to a gameobject of your choosing.

  • It's thread safe

     using System.Collections.Generic;
     using System.Linq;
     using UnityEngine;
    
     public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
     {
         #region  Variables
         protected static bool Quitting { get; private set; }
    
         private static readonly object Lock = new object();
         private static List<Singleton<T>>Dictionary<System.Type, Singleton<T>> _instances;
    
         public static T Instance
         {
             get
             {
                 if (Quitting)
                 {
                     return null;
                 }
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>Dictionary<System.Type, Singleton<T>>();
    
                     returnif (_instances.ContainsKey(typeof(T)))
                         .Where(singleton =>return singleton.GetType(T) == typeof_instances[typeof(T))];
                         .Select(singleton => (T)singleton)else
                         .FirstOrDefault();return null;
                 }
             }
         }
    
         #endregion
    
         #region  Methods
         private void OnEnable()
         {
             if (!Quitting)
             {
                 bool iAmSingleton = false;
    
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>Dictionary<System.Type, Singleton<T>>();
    
                     if (_instances.Where(singleton => singleton.GetTypeContainsKey() == this.GetType()).Any())
                         Destroy(this.gameObject);
                     else
                     {
                         iAmSingleton = true;
    
                         _instances.Add(this.GetType(), this);
    
                         DontDestroyOnLoad(gameObject);
                     }
                 }
    
                 if(iAmSingleton)
                     OnEnableCallback();
             }
         }
    
         private void OnApplicationQuit()
         {
             Quitting = true;
    
             OnApplicationQuitCallback();
         }
    
         protected abstract void OnApplicationQuitCallback();
    
         protected abstract void OnEnableCallback();
         #endregion
     }
    
  • It doesn't use FindObjectsOfType which is a performance killer

  • It's flexible in that it doesn't need to create a new empty gameobject during the game. You simply add it in the editor (or during the game) to a gameobject of your choosing.

  • It's thread safe

     using System.Collections.Generic;
     using System.Linq;
     using UnityEngine;
    
     public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
     {
         #region  Variables
         protected static bool Quitting { get; private set; }
    
         private static readonly object Lock = new object();
         private static List<Singleton<T>> _instances;
    
         public static T Instance
         {
             get
             {
                 if (Quitting)
                 {
                     return null;
                 }
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     return _instances
                         .Where(singleton => singleton.GetType() == typeof(T))
                         .Select(singleton => (T)singleton)
                         .FirstOrDefault();
                 }
             }
         }
    
         #endregion
    
         #region  Methods
         private void OnEnable()
         {
             if (!Quitting)
             {
                 bool iAmSingleton = false;
    
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     if (_instances.Where(singleton => singleton.GetType() == this.GetType()).Any())
                         Destroy(this.gameObject);
                     else
                     {
                         iAmSingleton = true;
    
                         _instances.Add(this);
    
                         DontDestroyOnLoad(gameObject);
                     }
                 }
    
                 if(iAmSingleton)
                     OnEnableCallback();
             }
         }
    
         private void OnApplicationQuit()
         {
             Quitting = true;
    
             OnApplicationQuitCallback();
         }
    
         protected abstract void OnApplicationQuitCallback();
    
         protected abstract void OnEnableCallback();
         #endregion
     }
    
  • It doesn't use FindObjectsOfType which is a performance killer

  • It's flexible in that it doesn't need to create a new empty gameobject during the game. You simply add it in the editor (or during the game) to a gameobject of your choosing.

  • It's thread safe

     using System.Collections.Generic;
     using System.Linq;
     using UnityEngine;
    
     public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
     {
         #region  Variables
         protected static bool Quitting { get; private set; }
    
         private static readonly object Lock = new object();
         private static Dictionary<System.Type, Singleton<T>> _instances;
    
         public static T Instance
         {
             get
             {
                 if (Quitting)
                 {
                     return null;
                 }
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new Dictionary<System.Type, Singleton<T>>();
    
                     if (_instances.ContainsKey(typeof(T)))
                         return (T)_instances[typeof(T)];
                     else
                         return null;
                 }
             }
         }
    
         #endregion
    
         #region  Methods
         private void OnEnable()
         {
             if (!Quitting)
             {
                 bool iAmSingleton = false;
    
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new Dictionary<System.Type, Singleton<T>>();
    
                     if (_instances.ContainsKey(this.GetType()))
                         Destroy(this.gameObject);
                     else
                     {
                         iAmSingleton = true;
    
                         _instances.Add(this.GetType(), this);
    
                         DontDestroyOnLoad(gameObject);
                     }
                 }
    
                 if(iAmSingleton)
                     OnEnableCallback();
             }
         }
    
         private void OnApplicationQuit()
         {
             Quitting = true;
    
             OnApplicationQuitCallback();
         }
    
         protected abstract void OnApplicationQuitCallback();
    
         protected abstract void OnEnableCallback();
         #endregion
     }
    
added 144 characters in body
Source Link
aBertrand
  • 176
  • 1
  • 3
  • It doesn't use FindObjectsOfType which is a performance killer

  • It's flexible in that it doesn't need to create a new empty gameobject during the game. You simply add it in the editor (or during the game) to a gameobject of your choosing.

  • It's thread safe

     using System.Collections.Generic;
     using System.Linq;
     using UnityEngine;
    
     public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
     {
         #region  Variables
         protected static bool Quitting { get; private set; }
    
         private static readonly object Lock = new object();
         private static List<Singleton<T>> _instances;
    
         public static T Instance
         {
             get
             {
                 if (Quitting)
                 {
                     return null;
                 }
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     return _instances
                         .Where(singleton => singleton.GetType() == typeof(T))
                         .Select(singleton => (T)singleton)
                         .FirstOrDefault();
                 }
             }
         }
    
         #endregion
    
         #region  Methods
         private void OnEnable()
         {
             if (!Quitting)
             {
                 bool iAmSingleton = false;
    
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     if (_instances.Where(singleton => singleton.GetType() == this.GetType()).Any())
                         Destroy(this.gameObject);
                     else
                     {
                         iAmSingleton = true;
    
                         _instances.Add(this);
    
                         DontDestroyOnLoad(gameObject);
                     }
                 } 
    
                 if(iAmSingleton)
                     OnEnableCallback();
             }
         }
    
         private void OnApplicationQuit()
         {
             Quitting = true;
    
             OnApplicationQuitCallback();
         }
    
         protected abstract void OnApplicationQuitCallback();
    
         protected abstract void OnEnableCallback();
         #endregion
     }
    
  • It doesn't use FindObjectsOfType which is a performance killer

  • It's flexible in that it doesn't need to create a new empty gameobject during the game. You simply add it in the editor (or during the game) to a gameobject of your choosing.

  • It's thread safe

     using System.Collections.Generic;
     using System.Linq;
     using UnityEngine;
    
     public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
     {
         #region  Variables
         protected static bool Quitting { get; private set; }
    
         private static readonly object Lock = new object();
         private static List<Singleton<T>> _instances;
    
         public static T Instance
         {
             get
             {
                 if (Quitting)
                 {
                     return null;
                 }
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     return _instances
                         .Where(singleton => singleton.GetType() == typeof(T))
                         .Select(singleton => (T)singleton)
                         .FirstOrDefault();
                 }
             }
         }
    
         #endregion
    
         #region  Methods
         private void OnEnable()
         {
             if (!Quitting)
             {
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     if (_instances.Where(singleton => singleton.GetType() == this.GetType()).Any())
                         Destroy(this.gameObject);
                     else
                     {
                         _instances.Add(this);
    
                         DontDestroyOnLoad(gameObject);
                     }
                 }
    
                 OnEnableCallback();
             }
         }
    
         private void OnApplicationQuit()
         {
             Quitting = true;
    
             OnApplicationQuitCallback();
         }
    
         protected abstract void OnApplicationQuitCallback();
    
         protected abstract void OnEnableCallback();
         #endregion
     }
    
  • It doesn't use FindObjectsOfType which is a performance killer

  • It's flexible in that it doesn't need to create a new empty gameobject during the game. You simply add it in the editor (or during the game) to a gameobject of your choosing.

  • It's thread safe

     using System.Collections.Generic;
     using System.Linq;
     using UnityEngine;
    
     public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
     {
         #region  Variables
         protected static bool Quitting { get; private set; }
    
         private static readonly object Lock = new object();
         private static List<Singleton<T>> _instances;
    
         public static T Instance
         {
             get
             {
                 if (Quitting)
                 {
                     return null;
                 }
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     return _instances
                         .Where(singleton => singleton.GetType() == typeof(T))
                         .Select(singleton => (T)singleton)
                         .FirstOrDefault();
                 }
             }
         }
    
         #endregion
    
         #region  Methods
         private void OnEnable()
         {
             if (!Quitting)
             {
                 bool iAmSingleton = false;
    
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     if (_instances.Where(singleton => singleton.GetType() == this.GetType()).Any())
                         Destroy(this.gameObject);
                     else
                     {
                         iAmSingleton = true;
    
                         _instances.Add(this);
    
                         DontDestroyOnLoad(gameObject);
                     }
                 } 
    
                 if(iAmSingleton)
                     OnEnableCallback();
             }
         }
    
         private void OnApplicationQuit()
         {
             Quitting = true;
    
             OnApplicationQuitCallback();
         }
    
         protected abstract void OnApplicationQuitCallback();
    
         protected abstract void OnEnableCallback();
         #endregion
     }
    
Source Link
aBertrand
  • 176
  • 1
  • 3

Here is my implementation of a singleton abstract class below. Here is how it stacks up against the 4 criteria

             Create object   Removes scene   Global    Keep across
           if not in scene?   duplicates?    access?   Scene loads?

             No (but why         Yes           Yes        Yes
             should it?)

It has a couple of other advantages compared to some of the other methods here:

  • It doesn't use FindObjectsOfType which is a performance killer

  • It's flexible in that it doesn't need to create a new empty gameobject during the game. You simply add it in the editor (or during the game) to a gameobject of your choosing.

  • It's thread safe

     using System.Collections.Generic;
     using System.Linq;
     using UnityEngine;
    
     public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
     {
         #region  Variables
         protected static bool Quitting { get; private set; }
    
         private static readonly object Lock = new object();
         private static List<Singleton<T>> _instances;
    
         public static T Instance
         {
             get
             {
                 if (Quitting)
                 {
                     return null;
                 }
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     return _instances
                         .Where(singleton => singleton.GetType() == typeof(T))
                         .Select(singleton => (T)singleton)
                         .FirstOrDefault();
                 }
             }
         }
    
         #endregion
    
         #region  Methods
         private void OnEnable()
         {
             if (!Quitting)
             {
                 lock (Lock)
                 {
                     if (_instances == null)
                         _instances = new List<Singleton<T>>();
    
                     if (_instances.Where(singleton => singleton.GetType() == this.GetType()).Any())
                         Destroy(this.gameObject);
                     else
                     {
                         _instances.Add(this);
    
                         DontDestroyOnLoad(gameObject);
                     }
                 }
    
                 OnEnableCallback();
             }
         }
    
         private void OnApplicationQuit()
         {
             Quitting = true;
    
             OnApplicationQuitCallback();
         }
    
         protected abstract void OnApplicationQuitCallback();
    
         protected abstract void OnEnableCallback();
         #endregion
     }