概要
シングルトンをシーンに配置しなくても使えるようにしたいと思い、作成中のゲームで実装した方法です
- ScriptableObjectにシングルトンを持ったPrefabを事前登録
- SingletonMonoBehaviourを継承 1
- 外部から呼ばれた際、継承先の型から一致するPrefabを見つけ、インスタンスする
コード
Prefabs.cs
[CreateAssetMenu(fileName = "Prefabs")]
public class Prefabs : ScriptableObject
{
[SerializeField]
private GameObject[] _prefabs;
private static Prefabs _instance;
public static Prefabs Instance
{
get
{
if (_instance == null)
{
_instance = Resources.Load<Prefabs>("Prefabs");
}
return _instance;
}
}
public static GameObject GetPrefabFromType<T>()
{
GameObject result = null;
foreach (var prefab in Prefabs.Instance._prefabs)
{
if (prefab.GetComponent<T>() != null)
{
result = prefab;
return result;
}
}
Debug.LogError(typeof(T) + " は登録されていないPrefabです");
return null;
}
}
使い方
-
SingletonMonoBehaviour内で、instanceがない時にGetPrefabFromTypeを呼ぶようにする
SingletonMonoBehaviour.cs
public class SingletonMonoBehaviour<T> : MonoBehaviourWithInit where T : MonoBehaviourWithInit
{
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
{
_instance = (T)FindObjectOfType(typeof(T));
if (_instance == null)
{
_instance = GameObject.Instantiate(Prefabs.GetPrefabFromType<T>().GetComponent<T>());
}
_instance.InitIfNeeded();
}
return _instance;
}
}
中略...
}
まとめ
これでシングルトンをシーンに配置せずとも、必要なときにインスタンスしてくれるようになります。
参照先をScriptableObjectで一元管理しているので、クラスごとにPrefabへの参照を持つ必要がありません。
また、シングルトン以外の用途でも、Prefabさえ登録しておけばどこからでも型指定で呼べるので、いろんな使い方ができます。