chore: initial commit
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
using UnityEngine;
|
||||
using System;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Persistent humble singleton, basically a classic singleton but will destroy any other older components of the same type it finds on awake
|
||||
/// </summary>
|
||||
public class MMPersistentHumbleSingleton<T> : MonoBehaviour where T : Component
|
||||
{
|
||||
/// whether or not this singleton already has an instance
|
||||
public static bool HasInstance => _instance != null;
|
||||
public static T Current => _instance;
|
||||
|
||||
protected static T _instance;
|
||||
|
||||
/// the timestamp at which this singleton got initialized
|
||||
[MMReadOnly]
|
||||
public float InitializationTime;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton design pattern
|
||||
/// </summary>
|
||||
/// <value>The instance.</value>
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = FindObjectOfType<T> ();
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject obj = new GameObject ();
|
||||
obj.hideFlags = HideFlags.HideAndDontSave;
|
||||
obj.name = typeof(T).Name + "_AutoCreated";
|
||||
_instance = obj.AddComponent<T> ();
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On awake, we check if there's already a copy of the object in the scene. If there's one, we destroy it.
|
||||
/// </summary>
|
||||
protected virtual void Awake ()
|
||||
{
|
||||
InitializeSingleton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton.
|
||||
/// </summary>
|
||||
protected virtual void InitializeSingleton()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
InitializationTime = Time.time;
|
||||
|
||||
DontDestroyOnLoad (this.gameObject);
|
||||
// we check for existing objects of the same type
|
||||
T[] check = FindObjectsOfType<T>();
|
||||
foreach (T searched in check)
|
||||
{
|
||||
if (searched!=this)
|
||||
{
|
||||
// if we find another object of the same type (not this), and if it's older than our current object, we destroy it.
|
||||
if (searched.GetComponent<MMPersistentHumbleSingleton<T>>().InitializationTime < InitializationTime)
|
||||
{
|
||||
Destroy (searched.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = this as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1069bbd270ccb95489ac88d734abbf9e
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,84 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Persistent singleton.
|
||||
/// </summary>
|
||||
public class MMPersistentSingleton<T> : MonoBehaviour where T : Component
|
||||
{
|
||||
[Header("Persistent Singleton")]
|
||||
/// if this is true, this singleton will auto detach if it finds itself parented on awake
|
||||
[Tooltip("if this is true, this singleton will auto detach if it finds itself parented on awake")]
|
||||
public bool AutomaticallyUnparentOnAwake = true;
|
||||
|
||||
public static bool HasInstance => _instance != null;
|
||||
public static T Current => _instance;
|
||||
|
||||
protected static T _instance;
|
||||
protected bool _enabled;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton design pattern
|
||||
/// </summary>
|
||||
/// <value>The instance.</value>
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = FindObjectOfType<T> ();
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject obj = new GameObject ();
|
||||
obj.name = typeof(T).Name + "_AutoCreated";
|
||||
_instance = obj.AddComponent<T> ();
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On awake, we check if there's already a copy of the object in the scene. If there's one, we destroy it.
|
||||
/// </summary>
|
||||
protected virtual void Awake ()
|
||||
{
|
||||
InitializeSingleton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton.
|
||||
/// </summary>
|
||||
protected virtual void InitializeSingleton()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (AutomaticallyUnparentOnAwake)
|
||||
{
|
||||
this.transform.SetParent(null);
|
||||
}
|
||||
|
||||
if (_instance == null)
|
||||
{
|
||||
//If I am the first instance, make me the Singleton
|
||||
_instance = this as T;
|
||||
DontDestroyOnLoad (transform.gameObject);
|
||||
_enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//If a Singleton already exists and you find
|
||||
//another reference in scene, destroy it!
|
||||
if(this != _instance)
|
||||
{
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32ed9853196ac60439e759122c98a09f
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Auto-referenced ScriptableObject instances of type T
|
||||
/// An example usage for ReferenceHolder<T> that can be used with any class type
|
||||
/// </summary>
|
||||
public class MMReferencedScriptableObject<T> : ScriptableObject where T : ScriptableObject
|
||||
{
|
||||
private MMReferenceHolder<T> _instances;
|
||||
protected virtual T Typed => _typed = _typed ?? this as T; private T _typed;
|
||||
|
||||
protected virtual void OnReferenced() {}
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
_instances.Reference(Typed);
|
||||
OnReferenced();
|
||||
// MMDebug.DebugLogInfo(ReferenceHolder<T>.Any != null, this);
|
||||
}
|
||||
|
||||
protected virtual void OnDisposed() {}
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
_instances.Dispose();
|
||||
OnDisposed();
|
||||
// MMDebug.DebugLogInfo(ReferenceHolder<T>.Any != null);
|
||||
}
|
||||
}
|
||||
|
||||
// using WeakReference to let GC collect those once Engine does not use them anymore
|
||||
public struct MMReferenceHolder<T> : IDisposable where T : class
|
||||
{
|
||||
private static List<WeakReference<T>> _instances = new List<WeakReference<T>>(2);
|
||||
|
||||
private WeakReference<T> _instance;
|
||||
public void Reference(T instance, bool cleanUp = false)
|
||||
{
|
||||
_instances = _instances ?? new List<WeakReference<T>>(1);
|
||||
if(cleanUp) CleanUp();
|
||||
if (instance != null)
|
||||
{
|
||||
_instance = new WeakReference<T>(instance);
|
||||
_instances.Add(_instance); // always adding at the end, to keep it cheap, do a CleanUp if needed
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
if (_instance != null) _instances?.Remove(_instance);
|
||||
}
|
||||
|
||||
public static void CleanUp() => RepackNonNullReferences();
|
||||
static void RepackNonNullReferences()
|
||||
{
|
||||
if (_instances == null) return;
|
||||
for(int n=_instances.Count-1; n >=0; --n)
|
||||
{
|
||||
if (!_instances[n].TryGetTarget(out T target))
|
||||
{
|
||||
_instances.RemoveAt(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static T Any => _instances != null && _instances.Count > 0 && _instances[0].TryGetTarget(out T target) ? target : null;
|
||||
public static IEnumerator<T> All
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instances == null) yield break;
|
||||
foreach (var inst in _instances)
|
||||
{
|
||||
if (inst.TryGetTarget(out T target))
|
||||
{
|
||||
yield return target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static T First(System.Func<T,bool> selector)
|
||||
{
|
||||
if (_instances == null) return null;
|
||||
if (selector == null) return Any;
|
||||
foreach (var inst in _instances)
|
||||
{
|
||||
if (inst.TryGetTarget(out T target) && selector(target))
|
||||
{
|
||||
return target;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfb03c2bcbc7bd64fbf6cc6081b9c441
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
58
Assets/Feel/MMTools/Core/MMSingletons/MMSingleton.cs
Normal file
58
Assets/Feel/MMTools/Core/MMSingletons/MMSingleton.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace MoreMountains.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Singleton pattern.
|
||||
/// </summary>
|
||||
public class MMSingleton<T> : MonoBehaviour where T : Component
|
||||
{
|
||||
protected static T _instance;
|
||||
public static bool HasInstance => _instance != null;
|
||||
public static T TryGetInstance() => HasInstance ? _instance : null;
|
||||
public static T Current => _instance;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton design pattern
|
||||
/// </summary>
|
||||
/// <value>The instance.</value>
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = FindObjectOfType<T> ();
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject obj = new GameObject ();
|
||||
obj.name = typeof(T).Name + "_AutoCreated";
|
||||
_instance = obj.AddComponent<T> ();
|
||||
}
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On awake, we initialize our instance. Make sure to call base.Awake() in override if you need awake.
|
||||
/// </summary>
|
||||
protected virtual void Awake ()
|
||||
{
|
||||
InitializeSingleton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton.
|
||||
/// </summary>
|
||||
protected virtual void InitializeSingleton()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_instance = this as T;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
Assets/Feel/MMTools/Core/MMSingletons/MMSingleton.cs.meta
Normal file
12
Assets/Feel/MMTools/Core/MMSingletons/MMSingleton.cs.meta
Normal file
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dbb0d969791b2a4f991754c03cf2579
|
||||
timeCreated: 1462623191
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user