내일배움캠프 Unity 9기/TIL

[Unity/TIL] - 싱글톤

song-ssi 2025. 6. 10. 12:22

1. 싱글톤. 왜 쓰나요?

특정 클래스가 게임 전체에서 단 하나만 존재하도록 보장하고,

전역 접근이 가능하도록 만들기 위해.

 

대표적으로 GameManager, SoundManager, UIController 등에 사용.

 

2. 기본 싱글톤 패턴

using UnityEngine;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    private void Awake()
    {
        // 인스턴스가 이미 존재하면 이 오브젝트는 제거
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }

        // 인스턴스 설정 및 씬 이동 시에도 유지
        Instance = this;
        DontDestroyOnLoad(gameObject);
    }
}

 

3. 사용 방법

GameManager.Instance.YourFunction();

 

4. 유의 사항

  • Awake() 안에서 인스턴스 중복 체크 꼭 해줘야 함.
  • DontDestroyOnLoad()를 쓰면 씬이 바뀌어도 오브젝트가 유지됨.
  • Instance에 직접 접근할 수 있도록 public static으로 선언.
  • Instance는 private set으로 외부에서 변경 불가능하게 막는 게 안전.
  •  

✅  UIManager 싱글톤 예제

using System.Collections.Generic;
using UnityEngine;

public class UIManager : MonoBehaviour
{
    public static UIManager Instance { get; private set; }

    [SerializeField] private List<GameObject> uiList; // Inspector에 등록

    private Dictionary<string, GameObject> uiDict = new Dictionary<string, GameObject>();

    private void Awake()
    {
        // 싱글톤 패턴
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }

        Instance = this;
        DontDestroyOnLoad(gameObject);

        // Dictionary로 등록
        foreach (GameObject ui in uiList)
        {
            if (ui != null)
                uiDict[ui.name] = ui;
        }
    }

    /// <summary>
    /// 특정 UI 창 열기
    /// </summary>
    public void OpenUI(string uiName)
    {
        if (uiDict.TryGetValue(uiName, out GameObject ui))
        {
            ui.SetActive(true);
        }
        else
        {
            Debug.LogWarning($"❗ UIManager: {uiName} UI를 찾을 수 없음");
        }
    }

    /// <summary>
    /// 특정 UI 창 닫기
    /// </summary>
    public void CloseUI(string uiName)
    {
        if (uiDict.TryGetValue(uiName, out GameObject ui))
        {
            ui.SetActive(false);
        }
    }

    /// <summary>
    /// 전체 UI 닫기
    /// </summary>
    public void CloseAllUI()
    {
        foreach (var ui in uiDict.Values)
        {
            ui.SetActive(false);
        }
    }
}

 

✅  사용법 예시

// UI 열기
UIManager.Instance.OpenUI("Inventory");

// UI 닫기
UIManager.Instance.CloseUI("Crafting");

// 전체 UI 닫기
UIManager.Instance.CloseAllUI();

 

✅  UI 오브젝트 등록 팁

  • UI 오브젝트는 Canvas 아래에 배치하고, uiList 리스트에 Inspector에서 등록하기.
  • 각각의 UI GameObject는 이름(gameObject.name)을 고유하게 설정해두기. (예: "Inventory", "Crafting" 등).