midas+son의 크리에이티브(creative) 이야기

싱글톤이란 디자인 패턴 중 하나로

실직적으로 class가 오직 한번만 생성되며 

어디서 호출하든 같은 instance를 가져오게하여

데이터를 공유하거나 관리할 수 있는 방법론이다.


이는 c++ 부터 Direct 3D로 게임을 만들 때에도 사용되어왔으며

각종 manager 처리를 할 때 유용하다.


보통 static으로 처리를 하거나

null이 아닐때에는 new 하지 않고

있는 값을 return하는데


유니티에서는 좀 다른 방법을 써야 하기에

이렇게 글을 남긴다.


아래는 C++에서 하던 데로 

유니티에서 작성한 싱글톤 class 이다.

유니티는 C# 스크립트를 사용했으므로 C#의 문법이 되겠다.


아래의 class를 상속하게 되면 그 class는 싱글톤이 되어 버린다.

(T는 템플릿, where 뒤에 있는 항목은 해당 템플릿이 가지는 속성이라고 생각하면 된다.)


public class Singleton<T> : MonoBehaviour where T : class, new()

{

    protected static T instance;


    public static T GetSingleton()

    {

        if (instance == null)

        {

            instance = new T();


            if (instance == null)

            {

//에러 메세지

                Debug.LogError(" ** Class Create Fail -> " + typeof(T));

            }

        }


        return instance;

    }

}


하지만 위와 같이 해버리면  아래와 같은 Warning이 발생 한다.


/*

 * 

You are trying to create a MonoBehaviour using the 'new' keyword.  

This is not allowed.  

MonoBehaviours can only be added using AddComponent().  

Alternatively, your script can inherit from ScriptableObject or no base class at all

UnityEngine.MonoBehaviour:.ctor()

Singleton`1:.ctor()

UtilManager:.ctor()

System.Activator:CreateInstance()

Singleton`1:GetSingleton() (at Assets/Manager/Singleton.cs:32)

Login:Start() (at Assets/Manager/Login.cs:8)

 * 

 */



대략...
컴포넌트가 없으면 위험 할수 있으니 
new로 동적 할당 하는 것은 권장 할 수 없다는 내용이다.
그리고 아래는 방법 들인데 ctor()은 어디 붙은 함수인지 의문이다.

여튼 유니티에서 new 동적 할당은 권장 되지 않으니
다른 방법을 찾았다.

Hierarchy 에 empty 로 manager용 오브젝트를 하나 만들고
미리 class가 있는 script를 add Component 한다.

그리고 그 Component를 찾아 사용하는 것이다.

위와 같은 방법을 쓰는 코드는 아래와 같다.

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    protected static T instance;

    public static T GetSingleton()
    {
        if (instance == null)
        {
            instance = (T)FindObjectOfType(typeof(T));
            
            if (instance == null)
            {
                Debug.LogError(" ** FindObjectOfType Fail -> " + typeof(T));
            }
        }

        return instance;
    }
}