You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.9 KiB

  1. using UnityEngine;
  2. namespace IPA.Utilities
  3. {
  4. /// <summary>
  5. /// Generate a persistent singleton which can be destroyed.
  6. /// </summary>
  7. /// <typeparam name="T"></typeparam>
  8. public class ModSingleton<T> : MonoBehaviour where T : MonoBehaviour
  9. {
  10. /// <summary>
  11. /// The stored reference for the instance
  12. /// </summary>
  13. protected static T _instance;
  14. /// <summary>
  15. /// The lock for the instance to prevent more than one being created.
  16. /// </summary>
  17. protected static object _lock = new object();
  18. /// <summary>
  19. /// Checks to see if the singleton if the singleton can be accessed
  20. /// </summary>
  21. public static bool IsSingletonAvailable => _instance != null;
  22. /// <summary>
  23. /// Noncapitalized version which points to the actual property.
  24. /// </summary>
  25. public static T instance => Instance;
  26. /// <summary>
  27. /// Creates and or returns the singleton
  28. /// </summary>
  29. public static T Instance
  30. {
  31. get
  32. {
  33. T result;
  34. object @lock = _lock;
  35. lock (@lock)
  36. {
  37. if (_instance == null)
  38. {
  39. _instance = (T)((object)FindObjectOfType(typeof(T)));
  40. if (FindObjectsOfType(typeof(T)).Length > 1)
  41. {
  42. IPA.Logging.Logger.log.Warn($"[Singleton] Something went really wrong - there should never be more than one singleton of {nameof(T)}");
  43. return _instance;
  44. }
  45. if (_instance == null)
  46. {
  47. GameObject gameObject = new GameObject();
  48. _instance = gameObject.AddComponent<T>();
  49. gameObject.name = $"{nameof(T)} Singleton";
  50. DontDestroyOnLoad(gameObject);
  51. }
  52. }
  53. result = _instance;
  54. }
  55. return result;
  56. }
  57. }
  58. /// <summary>
  59. /// Called when the singleton is enabled to prevent the singleton from being destroyed naturally
  60. /// </summary>
  61. private void OnEnabled()
  62. {
  63. DontDestroyOnLoad(this);
  64. }
  65. /// <summary>
  66. /// Destroys the singleton.
  67. /// </summary>
  68. public static void Destroy()
  69. {
  70. if (_instance != null)
  71. {
  72. _lock = new object();
  73. Destroy(_instance);
  74. }
  75. }
  76. /// <summary>
  77. /// Touches the instance to easily create it without having to assign it.
  78. /// </summary>
  79. public static void TouchInstance()
  80. {
  81. _ = Instance == null;
  82. }
  83. }
  84. }