mirror of
https://github.com/ConjureETS/Unity_Utils.git
synced 2026-03-24 04:50:58 +00:00
129 lines
3.4 KiB
C#
129 lines
3.4 KiB
C#
using System;
|
|
using JetBrains.Annotations;
|
|
using JohnsonUtils.Utilities;
|
|
using UnityEngine;
|
|
|
|
namespace JohnsonUtils.Common
|
|
{
|
|
public abstract class AbstractSingleton<T> : MonoBehaviour where T : AbstractSingleton<T>
|
|
{
|
|
protected static T SharedInstance;
|
|
|
|
[PublicAPI]
|
|
public static bool HasInstance => SharedInstance != null;
|
|
|
|
protected virtual void Awake()
|
|
{
|
|
try
|
|
{
|
|
SharedInstance = (T) Convert.ChangeType(this, typeof(T));
|
|
}
|
|
catch (InvalidCastException)
|
|
{
|
|
Debug.Assert(false, "Singleton's T type should be the derived class.");
|
|
}
|
|
}
|
|
|
|
protected void DestroyInstance()
|
|
{
|
|
if (gameObject.GetNumberOfComponents() == 1)
|
|
{
|
|
Destroy(gameObject);
|
|
}
|
|
else
|
|
{
|
|
Destroy(this);
|
|
}
|
|
}
|
|
|
|
protected virtual void OnApplicationQuit()
|
|
{
|
|
SharedInstance = null;
|
|
DestroyInstance();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Singleton class that can be loaded and unloaded with scenes.
|
|
/// </summary>
|
|
public abstract class Singleton<T> : AbstractSingleton<T> where T : Singleton<T>
|
|
{
|
|
public static T Instance
|
|
{
|
|
get
|
|
{
|
|
Debug.Assert(HasInstance, $"Trying to access a script of type {typeof(T).Name} that is not in the scene.");
|
|
|
|
return SharedInstance;
|
|
}
|
|
}
|
|
|
|
protected override void Awake()
|
|
{
|
|
if (HasInstance)
|
|
{
|
|
Debug.LogWarning($"New instance of type {typeof(T).Name} detected. " +
|
|
"This new instance is becoming the default instance.");
|
|
SharedInstance = (T) Convert.ChangeType(this, typeof(T));
|
|
return;
|
|
}
|
|
|
|
base.Awake();
|
|
}
|
|
|
|
protected virtual void OnDestroy()
|
|
{
|
|
if (SharedInstance == this)
|
|
{
|
|
SharedInstance = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Singleton class that is lazy loaded once and is only unloaded when the game exits.
|
|
/// </summary>
|
|
public abstract class PersistentSingleton<T> : AbstractSingleton<T> where T : PersistentSingleton<T>
|
|
{
|
|
[PublicAPI]
|
|
public static T Instance
|
|
{
|
|
get
|
|
{
|
|
CreateIfDoesNotExist();
|
|
return SharedInstance;
|
|
}
|
|
}
|
|
|
|
[PublicAPI]
|
|
public static void CreateIfDoesNotExist()
|
|
{
|
|
if (!HasInstance && Application.isPlaying)
|
|
{
|
|
CreateInstance();
|
|
}
|
|
}
|
|
|
|
private static void CreateInstance()
|
|
{
|
|
var instanceGameObject = new GameObject(typeof(T).Name);
|
|
instanceGameObject.AddComponent<T>();
|
|
}
|
|
|
|
protected override void Awake()
|
|
{
|
|
if (HasInstance)
|
|
{
|
|
Debug.Log($"Two or more instances of a singleton of type {typeof(T).Name} were found in the scene. " +
|
|
"The new instance of the singleton trying to register will be removed.");
|
|
|
|
DestroyInstance();
|
|
return;
|
|
}
|
|
|
|
DontDestroyOnLoadUtils.Add(gameObject);
|
|
base.Awake();
|
|
}
|
|
}
|
|
|
|
} |