1. 검색 "unity wiki generic singleton" 으로 찾은 제너릭 싱글턴 ( 탬플릿 ) 코드
: 쓰레드 세이프 및 에디터에서 어플리케이션 종료 후 비정상 행동까지 방지하게 구현 되어 있다.
using UnityEngine;
///
/// Inherit from this base class to create a singleton.
/// e.g. public class MyClassName : Singleton {}
///
public class Singleton : MonoBehaviour where T : MonoBehaviour
{
// Check to see if we're about to be destroyed.
private static bool m_ShuttingDown = false;
private static object m_Lock = new object();
private static T m_Instance;
///
/// Access singleton instance through this propriety.
///
public static T Instance
{
get
{
if (m_ShuttingDown)
{
Debug.LogWarning("[Singleton] Instance '" + typeof(T) +
"' already destroyed. Returning null.");
return null;
}
lock (m_Lock)
{
if (m_Instance == null)
{
// Search for existing instance.
m_Instance = (T)FindObjectOfType(typeof(T));
// Create new instance if one doesn't already exist.
if (m_Instance == null)
{
// Need to create a new GameObject to attach the singleton to.
var singletonObject = new GameObject();
m_Instance = singletonObject.AddComponent();
singletonObject.name = typeof(T).ToString() + " (Singleton)";
// Make instance persistent.
DontDestroyOnLoad(singletonObject);
}
}
return m_Instance;
}
}
}
private void OnApplicationQuit()
{
m_ShuttingDown = true;
}
private void OnDestroy()
{
m_ShuttingDown = true;
}
}
링크: http://wiki.unity3d.com/index.php/Singleton
2. Scene 로딩 시에 사라지게 할지 말지 결정 하는 DontDestroyOnLoad 함수 호출 여부를 설정 할 수 있는 싱글턴 예제코드
( private bool _persistent = true; )
public abstract class Singleton : Singleton where T : MonoBehaviour
{
#region Fields
[CanBeNull]
private static T _instance;
[NotNull]
// ReSharper disable once StaticMemberInGenericType
private static readonly object Lock = new object();
[SerializeField]
private bool _persistent = true;
#endregion
#region Properties
[NotNull]
public static T Instance
{
get
{
if (Quitting)
{
Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] Instance will not be returned because the application is quitting.");
// ReSharper disable once AssignNullToNotNullAttribute
return null;
}
lock (Lock)
{
if (_instance != null)
return _instance;
var instances = FindObjectsOfType();
var count = instances.Length;
if (count > 0)
{
if (count == 1)
return _instance = instances[0];
Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] There should never be more than one {nameof(Singleton)} of type {typeof(T)} in the scene, but {count} were found. The first instance found will be used, and all others will be destroyed.");
for (var i = 1; i < instances.Length; i++)
Destroy(instances[i]);
return _instance = instances[0];
}
Debug.Log($"[{nameof(Singleton)}<{typeof(T)}>] An instance is needed in the scene and no existing instances were found, so a new instance will be created.");
return _instance = new GameObject($"({nameof(Singleton)}){typeof(T)}")
.AddComponent();
}
}
}
#endregion
#region Methods
private void Awake()
{
if (_persistent)
DontDestroyOnLoad(gameObject);
OnAwake();
}
protected virtual void OnAwake() { }
#endregion
}
public abstract class Singleton : MonoBehaviour
{
#region Properties
public static bool Quitting { get; private set; }
#endregion
#region Methods
private void OnApplicationQuit()
{
Quitting = true;
}
#endregion
}
https://qastack.kr/gamedev/116009/in-unity-how-do-i-correctly-implement-the-singleton-pattern
3. 사용법
public class GameManager : Singleton<GameManager>
{
public int Score
{
get;
set;
}
// (Optional) Prevent non-singleton constructor use.
protected GameManager() { }
}
public class Player : MonoBehaviour
{
void Update()
{
if( Input.GetMouseButtonDown(0) )
{
GameManager.Instance.Score ++;
Debug.Log( GameManager.Instance.Score.ToString() );
}
}
}
'Unity3D' 카테고리의 다른 글
유니티3디의 JsonUtility 사용법 링크 (0) | 2020.04.21 |
---|---|
반복문을 가지는 코루틴 대기 하는 방법 - Coroutine Loop (0) | 2020.04.01 |
Simple Object Pooling for Unity3D (0) | 2020.03.04 |
Curved World with Surface Shader (0) | 2020.02.28 |
Loading Scene Asynchronously for Unity (0) | 2020.02.26 |