From ea51adc632f943e22eedb00c40d471fa74dcd13e Mon Sep 17 00:00:00 2001 From: Oliver Booth Date: Sat, 31 Dec 2022 14:49:32 +0000 Subject: [PATCH] Cache Singleton instance on Awake --- CHANGELOG.md | 2 +- X10D.Unity/src/Singleton.cs | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b0cdeb..b205879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -111,7 +111,7 @@ ### Changed - X10D: `TimeSpanParser.TryParse` now accepts a nullable string, and returns false if this input is null or empty -- X10D.Unity: Obsolesced `Singleton` +- X10D.Unity: `Singleton` now caches instance where possible ## [3.1.0] ### Added diff --git a/X10D.Unity/src/Singleton.cs b/X10D.Unity/src/Singleton.cs index 877a43c..bbead4e 100644 --- a/X10D.Unity/src/Singleton.cs +++ b/X10D.Unity/src/Singleton.cs @@ -7,12 +7,11 @@ namespace X10D.Unity; /// thread-safe. /// /// The type of the singleton. -[Obsolete("This implementation of the singleton pattern is discouraged, and this class will be removed in future. " + - "DO NOT USE THIS TYPE IN PRODUCTION.")] public abstract class Singleton : MonoBehaviour where T : Singleton { private static Lazy s_instanceLazy = new(CreateLazyInstanceInternal, false); + private static T? s_instance; /// /// Gets the instance of the singleton. @@ -20,7 +19,15 @@ public abstract class Singleton : MonoBehaviour /// The singleton instance. public static T Instance { - get => s_instanceLazy.Value; + get => s_instance ? s_instance! : s_instanceLazy.Value; + } + + /// + /// Called when the script instance is being loaded. + /// + protected virtual void Awake() + { + s_instance = (T?)this; } /// @@ -28,17 +35,24 @@ public abstract class Singleton : MonoBehaviour /// protected virtual void OnDestroy() { + s_instance = null; s_instanceLazy = new Lazy(CreateLazyInstanceInternal, false); } private static T CreateLazyInstanceInternal() { + if (s_instance) + { + return s_instance!; + } + if (FindObjectOfType() is { } instance) { + s_instance = instance; return instance; } var gameObject = new GameObject {name = typeof(T).Name}; - return gameObject.AddComponent(); + return s_instance = gameObject.AddComponent(); } }