diff --git a/IPA.Loader/Utilities/ModSingleton.cs b/IPA.Loader/Utilities/ModSingleton.cs
new file mode 100644
index 00000000..acc43ebe
--- /dev/null
+++ b/IPA.Loader/Utilities/ModSingleton.cs
@@ -0,0 +1,91 @@
+using UnityEngine;
+
+namespace IPA.Utilities
+{
+ ///
+ /// Generate a persistent singleton which can be destroyed.
+ ///
+ ///
+ public class ModSingleton : MonoBehaviour where T : MonoBehaviour
+ {
+ ///
+ /// The stored reference for the instance
+ ///
+ protected static T _instance;
+ ///
+ /// The lock for the instance to prevent more than one being created.
+ ///
+ protected static object _lock = new object();
+
+ ///
+ /// Checks to see if the singleton if the singleton can be accessed
+ ///
+ public static bool IsSingletonAvailable => _instance != null;
+
+ ///
+ /// Noncapitalized version which points to the actual property.
+ ///
+ public static T instance => Instance;
+
+ ///
+ /// Creates and or returns the singleton
+ ///
+ public static T Instance
+ {
+ get
+ {
+ T result;
+ object @lock = _lock;
+ lock (@lock)
+ {
+ if (_instance == null)
+ {
+ _instance = (T)((object)FindObjectOfType(typeof(T)));
+ if (FindObjectsOfType(typeof(T)).Length > 1)
+ {
+ IPA.Logging.Logger.log.Warn($"[Singleton] Something went really wrong - there should never be more than one singleton of {nameof(T)}");
+ return _instance;
+ }
+ if (_instance == null)
+ {
+ GameObject gameObject = new GameObject();
+ _instance = gameObject.AddComponent();
+ gameObject.name = $"{nameof(T)} Singleton";
+ DontDestroyOnLoad(gameObject);
+ }
+ }
+ result = _instance;
+ }
+ return result;
+ }
+ }
+
+ ///
+ /// Called when the singleton is enabled to prevent the singleton from being destroyed naturally
+ ///
+ private void OnEnabled()
+ {
+ DontDestroyOnLoad(this);
+ }
+
+ ///
+ /// Destroys the singleton.
+ ///
+ public static void Destroy()
+ {
+ if (_instance != null)
+ {
+ _lock = new object();
+ Destroy(_instance);
+ }
+ }
+
+ ///
+ /// Touches the instance to easily create it without having to assign it.
+ ///
+ public static void TouchInstance()
+ {
+ _ = Instance == null;
+ }
+ }
+}