-
유니티 쉽게 배우는 디자인 패턴 - 싱글톤 패턴 / Unity Design Pattern - Singleton Pattern유니티 2023. 11. 1. 13:00
싱글톤 패턴이란?
클래스의 인스턴스를 단 하나(Single)만 유지하고, 외부에서 어디에서든 접근할 수 있도록 하는 패턴입니다.
유니티를 입문하거나 디자인패턴을 모르더라도 가장 많이 들어봤을 패턴 중 하나일텐데요.
싱글 + 톤으로 단 하나임을 아시면 되겠습니다.
AudioManager.Instance로 접근하여 사운드를 재생하거나
VibrationManager.Instance로 접근하여 진동을 하거나
IAPManager.Instance로 접근하여 인앱결제를 하는 등
매니저급 클래스를 만들어 이미 많이 사용되고 있습니다.
왜 그러냐면 다른 스크립트에서 사운드를 재생하고 싶은데,
[SerializeField] AudioManager audioManager;
를 쓰고 인스펙터에 드래그하여 넣고 하는 과정이 불편할 수 있기 때문입니다.
싱글톤의 핵심은 클래스에 단 하나만 존재하게 하는 static 정적 변수를 사용하여,
변수를 바꾸지 않고 유지시키는 게 관건입니다.
아래 중에서 적절한 상황에 선택하시면 되는데 외부에서는 GameManager.Instance 형태로 접근이 가능합니다.
그리고 씬에 게임오브젝트를 하나 만들어 스크립트를 넣으시면 됩니다.
1. 임시적으로 간단하게 만드는 방법
GameManager.cs
using UnityEngine; public class GameManager : MonoBehaviour { public static GameManager Instance; void Awake() { Instance = this; } }
가장 단순한 코드이지만 단점도 존재합니다.
- 다른 스크립트에서 Awake에서 접근하고자 할 때,
스크립트의 실행순서가 항상 다르기 때문에 null이 불러와 질 수 있습니다. - 게임을 플레이 하지 않았을 때는 null이 불러와 집니다.
- 외부에서 Instance에 null을 넣을 수 있습니다.
2. 단일 씬에서 제네릭으로 만드는 방법
MonoSingleton.cs
using UnityEngine; public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour { static T instance; public static T Instance { get { if (instance == null) instance = FindFirstObjectByType<T>(); return instance; } } }
GameManager.cs
using UnityEngine; public class GameManager : MonoSingleton<GameManager> { }
단일 씬에서 재생중이 아닐때도 동작합니다.
- 씬 전환시 파괴됩니다.
3. 다중 씬에서 제네릭으로 만드는 방법
MonoSingleton.cs
using UnityEngine; public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour { static T instance; public static T Instance { get { if (instance == null) { instance = FindFirstObjectByType<T>(); if (instance == null) { GameObject obj = new GameObject(typeof(T).Name); instance = obj.AddComponent<T>(); } } return instance; } } /// <summary> /// protected override void Awake() { base.Awake(); ... } /// </summary> protected virtual void Awake() { if (instance == null) { instance = this as T; } else if (instance != this) { Destroy(gameObject); } DontDestroyOnLoad(instance.transform.root.gameObject); } }
씬을 불러오지 않고 재생을 바로 하는 Project Settings - Editor - Enter Play Mode Options를 켜도 잘 작동합니다.
재생중이 아닐 때도 작동합니다.
씬이 전환되어도 파괴되지 않습니다.
하이어라키의 자식으로 있다면 최상위 부모를 파괴하지 않습니다.
GameManager.cs
using UnityEngine; public class GameManager : MonoSingleton<GameManager> { protected override void Awake() { base.Awake(); } }
싱글톤을 달아줄 곳에서 Awake를 사용할 때는 protected override 로 구현해야 하며,
base.Awake()을 호출해야 부모의 싱글톤이 정상적으로 초기화됩니다.
4. 일반 클래스를 싱글톤으로 만드는 방법
GameManager.cs
public class GameManager { static GameManager instance; public static GameManager Instance { get { if (instance == null) instance = new GameManager(); return instance; } } }
MonoBehaviour를 상속받지 않은 일반적인 클래스는 위와같이 작성 후
씬에 드래그하지 않고 바로 사용하시면 됩니다.
마무리
싱글톤은 어디서든 편하게 접근한다는 장점이 있지만
그렇다고해서 대부분을 싱글톤을 사용하면 코드가 꼬이고 비대해집니다.
양날의 검을 잘 사용하시기 바랍니다.
'유니티' 카테고리의 다른 글
- 다른 스크립트에서 Awake에서 접근하고자 할 때,