프로그래밍/유니티
[유니티] MonoSingleton
갓똥
2022. 1. 14. 02:35
728x90
반응형
유니티에서 싱글톤을 쓰면서 MonoBehaviour를 상속받는 싱글톤과 아닌것을 나누는 필요성을 느꼈다.
만들고나니 왠만한 프로젝트에서 다 써도 될 것 같아 남김
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//씬 변경시 삭제가 되야하는 싱글톤들은 'class : MonoSingleton<T>, IDestructible' 의 형태로 선언한다.
interface IDestructible
{
}
//하이라키에서 보여져야 하는 싱글톤들은 'class : MonoSingleton<T>, IAppearable' 의 형태로 선언한다.
interface IAppearable
{
}
//싱글톤 관리 루트 클래스
public static class SingletonRoot
{
public const string SingletonRootName = "ManagerRoot";
private static GameObject _singletonRootInstance = null;
public static GameObject GetRootInstance()
{
if (_singletonRootInstance == null && Application.isPlaying)
{
_singletonRootInstance = new GameObject(SingletonRootName);
_singletonRootInstance.AddComponent<RectTransform>();
GameObject.DontDestroyOnLoad(_singletonRootInstance);
}
return _singletonRootInstance;
}
public static GameObject EditGetRootInstance()
{
if (_singletonRootInstance == null)
{
_singletonRootInstance = new GameObject(SingletonRootName);
}
return _singletonRootInstance;
}
public static void DestroyInstance()
{
GameObject.DestroyImmediate(_singletonRootInstance);
}
}
//매니저 클래스의 부모가 되는 MonoBehaviour 타입의 싱글턴 클래스
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
public const string StaticManagerOption = "(Static)";
public const string DynamicManagerOption = "(Dynamic)";
protected static T _instance = null;
public static bool IsNull()
{
return _instance == null;
}
public static T Instance
{
get
{
if(_instance == null)
{
_instance = FindObjectOfType<T>();
if(_instance == null)
{
CreateInstance();
}
else
{
SetInstanceObject(_instance.gameObject);
}
}
return _instance;
}
}
public static void CreateInstance()
{
if (_instance != null || Application.isPlaying == false)
return;
GameObject singletonObject = new GameObject(typeof(T).ToString());
_instance = singletonObject.AddComponent<T>();
if(_instance is IAppearable)
{
singletonObject.hideFlags = HideFlags.None;
}
else
{
singletonObject.hideFlags = HideFlags.HideInHierarchy;
}
SetInstanceObject(singletonObject);
}
private static void SetInstanceObject(GameObject singletonObject)
{
//인터페이스 클래스의 유무 따라 옵션형태로 기능이 추가된다.
if (_instance is IDestructible == false)
{
#if UNITY_EDITOR
singletonObject.name = singletonObject.name + StaticManagerOption;
#endif
if (Application.isPlaying)
DontDestroyOnLoad(singletonObject);
singletonObject.transform.parent = SingletonRoot.GetRootInstance().transform;
}
else
{
#if UNITY_EDITOR
singletonObject.name = singletonObject.name + DynamicManagerOption;
#endif
}
}
public static void DestroyInstance()
{
if (_instance == null)
return;
Destroy(_instance.gameObject);
_instance = null;
}
public virtual void OnDestroy()
{
//인터페이스 클래스의 유무 따라 옵션형태로 기능이 추가된다.
if (_instance is IDestructible || Application.isPlaying == false)
{
DestroyInstance();
}
}
public static void EditCreateInstance()
{
if (_instance != null)
return;
GameObject singletonObject = new GameObject(typeof(T).ToString());
_instance = singletonObject.AddComponent<T>();
if (_instance is IAppearable)
{
singletonObject.hideFlags = HideFlags.None;
}
else
{
singletonObject.hideFlags = HideFlags.HideInHierarchy;
}
EditSetInstanceObject(singletonObject);
}
private static void EditSetInstanceObject(GameObject singletonObject)
{
//인터페이스 클래스의 유무 따라 옵션형태로 기능이 추가된다.
if (_instance is IDestructible == false)
{
singletonObject.name = singletonObject.name + StaticManagerOption;
if (Application.isPlaying)
DontDestroyOnLoad(singletonObject);
singletonObject.transform.parent = SingletonRoot.EditGetRootInstance().transform;
}
else
{
singletonObject.name = singletonObject.name + DynamicManagerOption;
}
}
}
728x90
반응형