BITFALL/Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CreateSingleton.cs

135 lines
4.0 KiB
C#
Raw Normal View History

2024-03-18 18:20:23 +08:00
// Magica Cloth 2.
// Copyright (c) 2023 MagicaSoft.
// https://magicasoft.jp
using UnityEngine;
namespace MagicaCloth2
{
/// <summary>
/// 基本的なシングルトンテンプレート
/// ・シーンに無い場合は作成する
/// ・自動初期化呼び出し機能
/// ・DontDestroyOnLoad設定
/// ・実行前でもInstanceアクセス可能
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class CreateSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
/// <summary>
/// 初期化フラグ
/// </summary>
private static T initInstance;
private static bool isDestroy;
/// <summary>
/// Reload Domain 対応
/// ※残念ながらジェネリッククラスでは[RuntimeInitializeOnLoadMethod]が利用できないため、
/// この初期化関数を派生元で[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
/// を使用して呼び出さなければならない
/// </summary>
protected static void InitMember()
{
instance = null;
initInstance = null;
isDestroy = false;
}
public static T Instance
{
get
{
if (instance == null)
{
// FindObjectOfTypeはそれなりに負荷がかかるので注意
// 非アクティブのオブジェクトは発見できないので注意!
#if UNITY_2023_1_OR_NEWER
instance = FindFirstObjectByType<T>();
#else
instance = FindObjectOfType<T>();
#endif
if (instance == null && Application.isPlaying)
{
var obj = new GameObject(typeof(T).Name);
instance = obj.AddComponent<T>();
}
}
// 初期化
InitInstance();
return instance;
}
}
private static void InitInstance()
{
if (initInstance == null && instance != null && Application.isPlaying)
{
// シーン切り替えでもオブジェクトが消えないように設定
//DontDestroyOnLoad(instance.gameObject);
// 初期化呼び出し
var s = instance as CreateSingleton<T>;
s.InitSingleton();
initInstance = instance;
}
}
/// <summary>
/// インスタンスが存在する場合にTrueを返します
/// </summary>
/// <returns></returns>
public static bool IsInstance()
{
return instance != null && isDestroy == false;
}
/// <summary>
/// Awake()でのインスタンス設定
/// </summary>
protected virtual void Awake()
{
if (instance == null)
{
instance = this as T;
InitInstance();
}
else if (instance != this)
{
// 2つ目のコンポーネントを発見
var s = instance as CreateSingleton<T>;
s.DuplicateDetection(this as T);
// 2つ目のコンポーネントは破棄する
Destroy(this.gameObject);
}
}
protected virtual void OnDestroy()
{
// インスタンスクラスならば無効化フラグを立てる
if (instance == this)
{
isDestroy = true;
}
}
/// <summary>
/// 2つ目の破棄されるコンポーネントを通知
/// </summary>
/// <param name="duplicate"></param>
protected virtual void DuplicateDetection(T duplicate) { }
/// <summary>
/// 内部初期化
/// </summary>
protected abstract void InitSingleton();
}
}