Unity3D

Generic Singleton for Unity - 싱글턴 패턴 사용 하기

DragonTory 2020. 2. 25. 10:12
반응형

 

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() );

       }

    }

}

 

 

반응형