Last active
July 13, 2024 12:49
-
-
Save sassembla/2de4e864bd0918a06761356398a0d02e to your computer and use it in GitHub Desktop.
automated singleton holder for Unity. auto-initialize on Player boot time and well isolated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using UnityEngine; | |
public class SingletonHolder : MonoBehaviour { | |
private List<Base> instances = new List<Base>(); | |
private static SingletonHolder holderInstance; | |
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] private static void NewSingleton () { | |
GameObject o = new GameObject("SingletonHolder []"); | |
holderInstance = o.AddComponent<SingletonHolder>(); | |
GameObject.DontDestroyOnLoad(holderInstance); | |
} | |
public static T Get<T>() where T : Base, new() { | |
return holderInstance.GetInstance<T>(); | |
} | |
public static Base[] GetAll () { | |
return holderInstance.instances.ToArray(); | |
} | |
private T GetInstance<T>() where T : Base, new(){ | |
foreach (var instance in instances) { | |
if (instance is T) { | |
return (T)instance; | |
} | |
} | |
var t = new T(); | |
instances.Add(t); | |
NameUpdate(); | |
/* | |
本来のUnityのMonoBehaviour.Start はUnityがInstanceを生成したときだけ呼ばれるので、メインスレッドから呼ぶという制約があるが、 | |
このSingletonHolderにはその制約がない。 | |
が、その場合、この Start が呼ばれるのはサブスレッドになってしまうため、インスタンス内でエラーが出ると思う。 | |
そうなった場合、まずサブスレッドでこのメソッドを実行するのを見直してほしい。 | |
*/ | |
t.Awake(); | |
t.OnEnable(); | |
t.Start(); | |
return t; | |
} | |
public static bool Delete<T>() where T : Base, new() { | |
return holderInstance.DeleteInstance<T>(); | |
} | |
private bool DeleteInstance<T>() where T : Base, new() { | |
foreach (var instance in holderInstance.instances) { | |
if (instance is T) { | |
instances.Remove(instance); | |
NameUpdate(); | |
return true; | |
} | |
} | |
return false; | |
} | |
private void NameUpdate () { | |
// update this instance's name. | |
holderInstance.gameObject.name = "SingletonHolder [" + string.Join(", ", instances.Select(i => i.GetType().ToString()).ToArray()) + "]"; | |
} | |
/* | |
handler methods. | |
*/ | |
private void Start () { | |
foreach (var instance in holderInstance.instances) { | |
if (instance == null) continue; | |
instance.Start(); | |
} | |
} | |
private void OnGUI () { | |
foreach (var instance in holderInstance.instances) { | |
if (instance == null) continue; | |
instance.OnGUI(); | |
} | |
} | |
private void Update () { | |
foreach (var instance in holderInstance.instances) { | |
if (instance == null) continue; | |
instance.Update(); | |
} | |
} | |
private void LateUpdate () { | |
foreach (var instance in holderInstance.instances) { | |
if (instance == null) continue; | |
instance.LateUpdate(); | |
} | |
} | |
private void OnApplicationQuit () { | |
foreach (var instance in holderInstance.instances) { | |
if (instance == null) continue; | |
instance.OnApplicationQuit(); | |
} | |
} | |
private void OnDisable () { | |
foreach (var instance in holderInstance.instances) { | |
if (instance == null) continue; | |
instance.OnDisable(); | |
} | |
} | |
public class Base { | |
public virtual void Awake () {} | |
public virtual void OnEnable () {} | |
public virtual void Start () {} | |
public virtual void FixedUpdate () {} | |
public virtual void Update () {} | |
public virtual void LateUpdate () {} | |
public virtual void OnGUI () {} | |
public virtual void OnApplicationPause () {} | |
public virtual void OnDisable () {} | |
public virtual void OnApplicationQuit () {} | |
} | |
} |
・MonoBehaviourのシングルトンが欲しい場合と、それ以外とを分割
・インスタンスに対してのInspectorを提供するのはとても面白そう。値の編集も可能。
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Q1: MonoBehaviourのシングルトンが必須な機会ってあるの?
A1: ごめん、ないかも。