너무 자연스럽게 알고 있는 것들을 정리해보자.
내가 어떻게 이걸 배웠더라, 정확히 어떤 뜻이더라,를 알아야 남들이 이해하기 쉽게 알려줄 수 있다.
프로그래밍 디자인 패턴 중에 가장 빈번하게 사용하는 패턴이라 할 수 있다.
오직 한 개의 클래스 인스턴스만 갖도록 보장하고, 이에 대한 전역적인 접근점을 제공한다.
유니티 뉴비 시절, Manager 클래스에 일일히 필요한 스크립트를 가지고 있는 오브젝트를 할당 시켰다.
으악
이렇게 되면 새로운 스크립트를 할당할때마다 저렇게 코드를 추가해줘야한다는 불편함과, 씬 이동이 있을 때 관련 스크립트를 가지고 있는 오브젝트를 모두 옮겨야한다는 단점이 있었다.
난 꽤 오래 저런걸 싱글톤 패턴이라고 쓰고 있었다.
그러니 나같은 사람들이 없길 바라며 이 글을 써본다
쉽게 코드로 알아보자
using UnityEngine;
/// <summary>
/// 싱글톤 베이스
/// </summary>
/// <typeparam name="T">Singleton 클래스를 상속받은 T타입만 올 수 있음</typeparam>
public abstract class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
// 씬 변경 시 파괴하지 않을 건지
public bool isDontDestroy;
// 인스턴스 객체를 담을 필드
private static T _instance;
public static T Instance
{
get
{
// 인스턴스가 없는지 확인
if (_instance == null)
{
// 없다면 씬에서 찾음
_instance = FindObjectOfType(typeof(T)) as T;
// 찾아도 없다면
if (_instance == null)
{
// 생성하여 T타입 컴포넌트를 붙임
var go = new GameObject(typeof(T).ToString());
_instance = go.AddComponent<T>();
}
}
// 결과적으로 반환 시에는 인스턴스는 무조건 존재함
return _instance;
}
}
public virtual void Awake()
{
// Awake가 들어왔다는 것은 씬 장면의 하이라키상에 객체가 존재한다는 뜻
// 이 때 경우는 2가지 -> 내가 미리 씬에 T타입 스크립트를 갖는 객체를 배치했거나
// 다른 스크립트를 통해 T타입 인스턴스에 접근하여 객체가 생성된 경우
// 이 때 싱글톤 사용에 규칙성을 부여
// ex) 난 무조건 싱글톤을 갖는 객체라면 씬에 미리 스크립트를 갖는 객체를 배치하는 식으로 사용한다
// 위의 경우, 타 스크립트에서 awake 시점보다 빠른 시점에 t타입객체에 접근하지 않았다면
// 인스턴스는 무조건 null임
// 그럼 null이 아닌 경우, 씬에 t타입 객체가 하나 더 생성된 경우
// 해당 객체를 파괴함으로써 결과적으로 단 하나의 인스턴스만을 유지할 수 있다.
if (_instance == null)
{
_instance = this as T;
if (isDontDestroy)
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
그럼 사용은 어떻게 할까?
요로코롬 상속받고 T타입 클래스를 상속하여 쓸 수 있다
너무 편하게 접근 할 수 있다 보니까, 마구잡이로 사용하여 코드가 꼬일 수 있다.
이렇게 말하긴 하지만, 기능경기대회같은 시간 제한이 있는 상황에는 자주 사용했다.
Manager 스크립트만 접근 할 수 있게 해보자.
기능별로 묶여 정리되어 있게 해두는 것이다.