필자는 게임 개발할때 꼭 하는 루틴 중 하나가 프로젝트 생성 후 싱글톤 제너릭 클래스를 생성해주는 것 입니다. 항상 모든 게임에서 싱글톤 패턴을 써왔기 때문에, 개발 초기 단계부터 만들어주는 편입니다.
간단하게 싱글톤 패턴에 대한 설명을 하고, 제너릭 클래스로 구현하는 방법을 서술하도록 하겠습니다.
싱글톤 패턴이란?
싱글톤 패턴은 간단하게 말해 객체의 인스턴스가 단 하나만 존재하도록 유일성을 보장해주는 패턴입니다. 따라서 생성자가 여러번 호출된다 하더라도 이전에 생성된 인스턴스를 반환함으로써 메모리 관리에서 우위를 점할 수 있습니다. 또한 전역에서 사용하는 인스턴스이기 때문에 데이터 공유 측면에서도 쉽게 공유가 가능합니다.
제너릭으로 싱글톤 패턴 구현하기
모노싱글톤
using UnityEngine;
public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T Instance {
get {
if (instance == null) {
GameObject obj = GameObject.Find(typeof(T).Name);
if (obj == null) {
obj = new GameObject(typeof(T).Name);
instance = obj.AddComponent<T>();
} else {
instance = obj.GetComponent<T>();
}
}
return instance;
}
}
void Awake() => DontDestroyOnLoad(gameObject);
}
Scene에서 컴포넌트 이름의 인스턴스가 존재하는지 확인하고, 만일 존재하지 않는다면 컴포넌트 이름의 인스턴스를 생성해줍니다.
MonoBehaviour를 상속할 경우 Hierarchy에 존재하게 되고, Awake()
, Update()
와 같은 함수를 사용할 수 있습니다. 하지만 Scene 이동 시에 이전 Scene에서 사용하던 인스턴스를 사용할지, 아니면 새로운 씬의 Hierarchy에 있는 인스턴스를 사용할지를 선택해야 합니다. 또한, 유니티 오브젝트가 공통적으로 갖는 Transform 컴포넌트를 필수적으로 갖게 되어 메모리 점유에 불리함이 있을 수 있습니다. 보통 싱글톤으로 구현하는 Manager 인스턴스의 경우 Transform 컴포넌트가 필요없고, 데이터 관리 및 로직 처리 위주의 작업을 하기 때문에 꼭 MonoBehaviour를 상속받을 필요가 없습니다.
MonoBehaviour를 상속받지 않는 싱글톤 클래스
public class Singleton<T> where T : class, new()
{
private static T instance;
public static T Instance {
get {
if (instance == null) {
instance = new T();
}
return instance;
}
}
}
위 방식을 사용하면 MonoBehaviour를 상속받지 않는 제너릭 싱글톤 클래스를 만들 수 있습니다. 위 코드에서는 new()
제약 조건을 통해 기본 생성자가 있는 클래스만을 허용하도록 하였습니다. 이를 통해 MonoBehaviour를 상속받지 않는 일반적인 클래스에서도 해당 싱글톤을 사용할 수 있습니다.
사용 방법
모노 싱글톤과 일반 싱글톤 모두 사용 방법은 아래와 동일합니다.
public class Manager : Singleton<Manager> {
protected Manager() {
// 초기화 로직
}
// 클래스 기능 구현
public void Func() {
Debug.Log("Func 1");
}
}
Manager 클래스가 Singleton<Manager>
를 상속받아 싱글톤으로 만들어졌습니다. 또한 외부에서 직접 인스턴스를 생성하지 못하도록 하기 위해 생성자를 protected
로 선언해주었습니다.
public class Test : MonoBehaviour {
void Start() {
// 싱글톤 인스턴스 접근
Manager.Instance.Func();
}
}
Test 클래스에서 Manager.Instance
를 통해 싱글톤 인스턴스에 접근하여 해당 기능을 호출할 수 있습니다. 여기서 중요한 점은 직접 생성자를 호출해서 인스턴스를 만들 수 없고, 항상 Manager.Instance
를 통해서만 인스턴스에 접근해야 한다는 것 입니다.
'GAME > Unity' 카테고리의 다른 글
Unity: Flask를 이용한 HTTP 통신 구현 (0) | 2023.11.06 |
---|