Unity에서의 Singleton 1편 - 싱글턴 클래스 만들기

종잇장·2022년 5월 23일
2

Unity에서의 Singleton

목록 보기
1/2
post-thumbnail

머리말

이 글과 이후 글에서는 싱글턴에 대한 설명보다는 Unity에서 구현해보는데 집중해보고, 문제점과 해결방법을 이야기해볼 예정입니다.
싱글턴에 대한 좀 더 상세하고 원론적인 내용이 필요하신 분은 다른 글을 보시면 될 것 같습니다.


1. Singleton

설명

싱글턴(Singleton)이라고 하면 디자인 패턴(Design Pattern) 중, 정말 많이 쓰이는 패턴 중 하나입니다.

싱글턴 패턴은 클래스를 글로벌로 접근 가능하도록하는 방법 중 하나인데, 만들기도 간단하고 만들어두면 정말 편하게 사용 가능해서 여기저기 많이 쓰이는 패턴입니다.

구현

public class ItemInventory
{
    static ItemInventory m_Instance = null;
    public static ItemInventory Instance
    {
        get
        {
            if (m_Instance == null) m_Instance = new ItemInventory();
            return m_Instance;
        }
    }

    public Item GetItem(int itemID) { /* ... */ }
    public bool AddItem(Item item) { /* ... */ }
}

간단한 예제로 ItemInventory라는 싱글턴 클래스를 만들어보았습니다.
static 변수로 클래스를 Instance로 접근하도록 구현하면 됩니다.

//프로퍼티로 구현
static ItemInventory m_Instance = null;
public static ItemInventory Instance
{
    get
    {
        if (m_Instance == null) m_Instance = new ItemInventory();
        return m_Instance;
    }
}

//readonly변수로 구현
public readonly static ItemInventory Instance = new ItemInventory();

//함수로 구현
static ItemInventory m_Instance = null;
public static ItemInventory GetInstance()
{
    if (m_Instance == null) m_Instance = new ItemInventory();
        return m_Instance;
}

저의 경우에는 프로퍼티를 좋아해서 프로퍼티로 구현했는데, 위 코드처럼 readonly변수로 Instance를 선언하거나 프로퍼티 대신 함수로 구현해도 무방합니다.

사용

var item = ItemInventory.Instance.GetItem(1000);

실제 호출되는 부분은 이렇게 Instance로 접근해서 싱글턴 클래스의 맴버를 호출하면 됩니다.

구현 (Template)

public class SingletonTemplate<T> where T : class, new()
{
    static T m_Instance = null;
    public static T Instance
    {
        get
        {
            if (m_Instance == null) m_Instance = new T();
            return m_Instance;
        }
    }
}

public class ItemInventory : SingletonTemplate<ItemInventory>
{
    public Item GetItem(int itemID) { /* ... */ }
    public bool AddItem(Item item) { /* ... */ }
}

추후에 재활용성을 고려하여 Template으로 구현한 예제입니다.
그렇게 긴 코드가 아니긴 하지만, 추후에 싱글턴에 기능이 더 추가되거나 싱글턴 클래스들의 관리가 필요할 경우 유용하게 쓰입니다.


2. MonoBehaviour Singleton

설명

Unity에서는 싱글턴 클래스가 MonoBehaviour의 기능을 이용해야할 경우들이 존재하는데, 이러한 문제를 해결하기 위해 Unity에서 사용하는 싱글턴입니다.

구현

public class MonoBehaviourSingletonTemplate<T> : MonoBehaviour where T : MonoBehaviour
{
    static T m_Instance = null;
    public static T Instance
    {
        get
        {
            if (m_Instance == null)
            {
                var obj = new GameObject(typeof(T).Name);
                m_Instance = obj.AddComponent<T>();
            }
            return m_Instance;
        }
    }
    
    protected void Awake()
    {
    	DontDestroyOnLoad(gameObject);
    }
}

MonoBehaviour는 Unity에서 사용하는 Component클래스이기 때문에, GameObjectAddComponent함수로 추가하여 사용해야 합니다.

Instance 프로퍼티 내부 코드를 보시면 바로 아실 거라 생각됩니다.

사용 이유

아마도 다음 편에서 MonoBehaviour 싱글턴에 대해 좀 더 상세히 장단점을 다뤄볼 예정이긴 한데, 우선 이러한 싱글턴을 Unity에서 주로 사용되는 경우는 아래처럼 몇가지 상황을 위해 사용됩니다.

  1. Update, LateUpdate, FixedUpdate 등등 MonoBehaviour 함수 사용해야 할 경우
    1.1. MonoBehaviour: https://docs.unity3d.com/ScriptReference/MonoBehaviour.html
    1.2. 함수 호출 순서: https://docs.unity3d.com/Manual/ExecutionOrder.html
  2. Coroutine 사용해야 할 경우
  3. SendMessage로 전달받아야 할 경우

마무리

우선 이번 편에서 간단하게 싱글턴 클래스들을 만들어봤습니다.

사실 첫 글이라 어떻게 혹은 어떤 구성으로 쓰는 게 좋을지 고민하고 조사해보느라 시간이 너무 많이 소모되었던 것 같네요.

다음 편부터는 할 말이 정말 많아서 첫 편은 짧고 쉬운 소재로 골랐는데 글이 잘 쓰였을지 잘 모르겠네요.

길지 않은 글이였지만 봐주셔서 감사합니다.

1개의 댓글

comment-user-thumbnail
2022년 12월 31일

정리를 너무나 상세하고 친절하게 해주셔서 뒤늦게 유니티 개발에 뛰어든 저에게 큰 도움이 되었습니다! 감사합니다 :)

답글 달기