이 글과 이후 글에서는 싱글턴에 대한 설명보다는 Unity에서 구현해보는데 집중해보고, 문제점과 해결방법을 이야기해볼 예정입니다.
싱글턴에 대한 좀 더 상세하고 원론적인 내용이 필요하신 분은 다른 글을 보시면 될 것 같습니다.
Wikipedia: https://ko.wikipedia.org/wiki/%EC%8B%B1%EA%B8%80%ED%84%B4_%ED%8C%A8%ED%84%B4
싱글턴(Singleton)이라고 하면 디자인 패턴(Design Pattern) 중, 정말 많이 쓰이는 패턴 중 하나입니다.
싱글턴 패턴은 클래스를 글로벌로 접근 가능하도록하는 방법 중 하나인데, 만들기도 간단하고 만들어두면 정말 편하게 사용 가능해서 여기저기 많이 쓰이는 패턴입니다.
1. Singleton
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)
{
//TODO
return default;
}
public bool AddItem(Item item)
{
//TODO
return default;
}
}
간단한 예제로 ItemInventory라는 싱글턴 클래스를 만들어보았습니다.
static 변수로 클래스를 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로 접근해서 싱글턴 클래스의 맴버를 호출하면 됩니다.
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)
{
//TODO
return default;
}
public bool AddItem(Item item)
{
//TODO
return default;
}
}
추후에 재활용성을 고려하여 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클래스이기 때문에, GameObject에 AddComponent함수로 추가하여 사용해야 합니다.
Instance 프로퍼티 내부 코드를 보시면 바로 아실 거라 생각됩니다.
아마도 다음 편에서 MonoBehaviour 싱글턴에 대해 좀 더 상세히 장단점을 다뤄볼 예정이긴 한데, 우선 이러한 싱글턴을 Unity에서 주로 사용되는 경우를 나열해보자면,
- Update, LateUpdate, FixedUpdate 등등 MonoBehaviour 함수 사용해야 할 경우
- Coroutine 사용해야 할 경우
- SendMessage로 전달받아야 할 경우
이 정도 될 것 같고 상황과 경우들이 더 있지만 다음 편에 좀 더 다뤄보도록 하겠습니다.
마무리
우선 이번 편에서 간단하게 싱글턴 클래스들을 만들어봤습니다.
사실 블로그 첫 글이라 어떻게 혹은 어떤 구성으로 쓰는 게 좋을지 고민하고 조사해보느라 시간이 너무 많이 소모되었던 것 같네요.
다음 편부터는 할 말이 정말 많아서 첫 편은 짧고 쉬운 소재로 골랐는데 글이 잘 쓰였을지 잘 모르겠네요.
길지 않은 글이였지만 봐주셔서 감사합니다.
'Unity Tips' 카테고리의 다른 글
Unity에서 Enum.Parse함수 GC 발생 줄이기 (0) | 2022.05.01 |
---|---|
Unity에서 계층이 있는 데이터 저장 (JSON vs XML vs Scriptable Object) (0) | 2022.04.30 |
Unity에서 C++코드(cpp) Native Plug-ins 사용하기 (0) | 2022.03.27 |
Unity에서의 Singleton 3편 - Singleton끼리 서로 참조하는 문제 (0) | 2022.03.09 |
Unity에서의 Singleton 2편 - MonoBehaviour Singleton의 문제점 (0) | 2022.03.06 |