Menu
CoddyTech

제네릭 싱글턴

Coddy Unity 여정의 Unity 게임 아키텍처 섹션에 포함된 레슨. 64개 중 43번째.

3절의 싱글턴은 각 매니저에서 반복되는 다섯 줄, 즉 static Instance, 이를 설정하는 Awake, 중복 확인으로 이루어져 있습니다. 제네릭 기본 클래스에 이 코드를 한 번만 작성합니다. 각 매니저는 이 클래스를 상속하고, 자신의 타입을 지정합니다:

public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    public static T Instance { get; private set; }

    protected virtual void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this as T;
    }
}

public class ScoreManager : Singleton<ScoreManager>
{
    public int score;
    public void Add(int points) { score += points; }
}

public class SoundManager : Singleton<SoundManager>
{
    public void Play(string clip) { Debug.Log("Playing " + clip); }
}
// 어떤 스크립트에서든
ScoreManager.Instance.Add(10);
SoundManager.Instance.Play("coin");

제네릭 클래스의 static 멤버는 그 클래스로 생성된 각 타입에 속합니다. Singleton<ScoreManager>와 Singleton<SoundManager>는 각각 Instance를 가진 별개의 타입이므로 매니저들은 하나의 Instance를 공유하지 않습니다. ScoreManager.Instance는 이미 ScoreManager 타입이며, 이것이 바로 T를 사용하는 이유입니다. 기본 클래스 안에서 this는 Singleton<T>로만 알려져 있으므로, this as T를 사용해 이를 실제 매니저 타입으로 전달합니다.

기본 클래스는 abstract입니다. Unity는 오브젝트에 매니저만 추가합니다. 자체 Awake가 필요한 매니저는 일반적인 void Awake()를 작성하면 안 됩니다. 그러면 기본 클래스의 메서드를 숨기게 되고(컴파일러가 경고합니다), Unity는 매니저의 메서드만 호출하여 Instance가 설정되지 않습니다. 이를 오버라이드하고 먼저 기본 메서드를 호출하세요:

protected override void Awake()
{
    base.Awake();
    score = 0;
}
challenge icon

챌린지

중급

두 매니저 모두 씬을 불러와도 유지되는 기반을 갖게 하세요.

  1. PersistentSingleton에 protected virtual void Awake()를 작성하세요. 첫 번째 인스턴스는 Instance가 되어 유지되고(DontDestroyOnLoad), 이후에 생성된 인스턴스는 자기 자신을 제거합니다.
  2. Wallet과 MusicPlayer가 이를 상속하도록 하고, 이들의 Instance와 Wallet의 Awake를 삭제하세요.
  3. MusicPlayer에서 Awake를 재정의하세요. 먼저 base.Awake()를 호출한 다음, 자신이 Instance라면 Now playing: Adventure를 로그로 출력합니다.

‘플레이’를 누르고 숲에 갔다가 돌아오세요. 코인 1개가 있어야 합니다. 그런 다음 ‘확인’을 누르세요.

직접 해보기

using UnityEngine;

public abstract class PersistentSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
    public static T Instance { get; private set; }

    // Awake: 씬을 로드해도 첫 번째 인스턴스는 유지하고, 이후 생성된 인스턴스는 모두 제거한다
}

Unity 게임 아키텍처의 모든 레슨

직접 연습해 보세요: Unity 플레이그라운드