본문 바로가기
STUDY/디자인패턴

Singletone 싱글톤 패턴 ★★★

by 램플릿 2024. 7. 12.

디자인패턴을 사용하는 이유 : 재사용성, 가독성, 유지보수성, 확장성

 

참고자료

https://ittrue.tistory.com/550

 

보통 싱글톤 패턴을 사용해 각 매니저를 게임 전체에서 한 번만 인스턴스화하여 공유합니다. 이를 통해 각 매니저가 일관된 상태를 유지하고 게임 내 여러 부분 간의 통합된 상호작용을 가능하게 합니다.

 

  • SceneManager (장면 관리자):
    • Scene 전환을 관리하는 매니저입니다.
    • 게임 플레이 중 다른 장면으로의 전환, 장면 간 데이터 전달 등을 처리합니다.
  • GameManager (게임 관리자):
    • 게임의 전반적인 흐름을 관리합니다.
    • 게임의 시작과 종료, 점수 관리, 난이도 설정 등의 전반적인 게임 로직을 담당합니다.
  • InputManager (입력 관리자):
    • 사용자의 입력을 관리하고 처리합니다.
    • 키보드, 마우스, 터치 입력을 받아 게임 내 동작으로 변환하는 역할을 합니다.
  • AudioManager (오디오 관리자):
    • 게임 내 사운드와 관련된 모든 것을 관리합니다.
    • 배경 음악 재생, 효과음 트리거, 볼륨 조절 등을 담당합니다.
  • UIManager (UI 관리자):
    • 게임의 사용자 인터페이스를 관리합니다.
    • UI 요소의 표시, 갱신, 상호작용에 대한 이벤트 처리를 담당합니다.

 

 

프리팹을 바인딩하는 싱글톤

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Singleton_PrefabUsing : MonoBehaviour
{
    public GameObject Prefab1;
    
    private static Singleton_PrefabUsing _instance;

    // Public static property to access the instance
    public static Singleton_PrefabUsing Instance
    {
        get
        {
            // If the instance is null, find an instance in the scene
            if (_instance == null)
            {
                _instance = FindObjectOfType<Singleton_PrefabUsing>();

                // If there is no instance in the scene, create a new one
                if (_instance == null)
                {
                    // GameObject singleton = new GameObject("Singleton");
                    // _instance = singleton.AddComponent<Singleton>();

                    GameObject singletonPrefab = Resources.Load("Singleton") as GameObject;
                    GameObject singletonInstance = Instantiate(singletonPrefab);
                    if (singletonInstance != null) _instance = singletonInstance.GetComponent<Singleton_PrefabUsing>();
                }
            }

            return _instance;
        }
    }

    // Awake method to enforce singleton property
    private void Awake()
    {
        // if (_instance == null)
        // {
        //     _instance = this;
        //     DontDestroyOnLoad(gameObject); // This makes sure the instance is not destroyed on scene load
        // }
        // else if (_instance != this)
        // {
        //     Destroy(gameObject); // Destroy this instance if another instance already exists
        // }
    }

    public void TestFunction()
    {
        Debug.Log("TestFunction");
    }
}

 

 

씬에 있는 게임오브젝트를 바인딩할때 사용하는 싱글톤코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Singleton_GameObjectUsing : MonoBehaviour
{
    public GameObject GameObject1;
    
    private static Singleton_GameObjectUsing _instance;

    // Public static property to access the instance
    public static Singleton_GameObjectUsing Instance
    {
        get
        {
            // If the instance is null, find an instance in the scene
            if (_instance == null)
            {
                _instance = FindObjectOfType<Singleton_GameObjectUsing>();

                // If there is no instance in the scene, create a new one
                // if (_instance == null)
                // {
                //     // GameObject singleton = new GameObject("Singleton");
                //     // _instance = singleton.AddComponent<Singleton>();
                //
                //     GameObject singletonPrefab = Resources.Load("Singleton") as GameObject;
                //     GameObject singletonInstance = Instantiate(singletonPrefab);
                //     if (singletonInstance != null) _instance = singletonInstance.GetComponent<Singleton_GameObjectUsing>();
                // }
            }

            return _instance;
        }
    }

    // Awake method to enforce singleton property
    private void Awake()
    {
        // if (_instance == null)
        // {
        //     _instance = this;
        //     DontDestroyOnLoad(gameObject); // This makes sure the instance is not destroyed on scene load
        // }
        // else if (_instance != this)
        // {
        //     Destroy(gameObject); // Destroy this instance if another instance already exists
        // }
    }

    public void TestFunction()
    {
        Debug.Log("TestFunction");
    }
}

 

한 씬에서 끝내고싶지 않을 때 사용하는 싱글톤

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// 씬 내에 오브젝트를 바인딩 하지 않는 구조이면서
// 데이터를 다른 씬으로 넘어가도 누적되서 사용해야 하거나
// 씬 로드와는 상관없이 사용해야 하는 경우에는 
// DontDestroyOnLoad를 통해서 삭제되지 않게 한다.
public class Singleton_Immortal : MonoBehaviour
{
    public GameObject Prefab1;
    public int TotalTime;
    
    private static Singleton_Immortal _instance;

    // Public static property to access the instance
    public static Singleton_Immortal Instance
    {
        get
        {
            // If the instance is null, find an instance in the scene
            if (_instance == null)
            {
                _instance = FindObjectOfType<Singleton_Immortal>();

                // If there is no instance in the scene, create a new onec
                if (_instance == null)
                {
                    GameObject singletonPrefab = Resources.Load("Singleton") as GameObject;
                    GameObject singletonInstance = Instantiate(singletonPrefab);
                    if (singletonInstance != null) _instance = singletonInstance.GetComponent<Singleton_Immortal>();
                }
            }

            return _instance;
        }
    }

    // Awake method to enforce singleton property
    private void Awake()
    {
        if (_instance == null)
        {
            _instance = this;
            DontDestroyOnLoad(gameObject); // This makes sure the instance is not destroyed on scene load
        }
        else if (_instance != this)
        {
            Destroy(gameObject); // Destroy this instance if another instance already exists
        }
    }

    public void TestFunction()
    {
        Debug.Log("TestFunction");
    }
}

 

 

쓰레드를 쓰거나 병렬적으로 수행 시 동시성이 보장되어야 할 때 아래와 같은 코드를 사용하여 락을 걸어준다.

using UnityEngine;

public class GameManager : MonoBehaviour
{
    // Static instance of GameManager
    private static GameManager _instance;

    // Lock object for thread safety
    private static readonly object _lock = new object();

    // Public static property to access the instance
    public static GameManager Instance
    {
        get
        {
            // Double-check locking for thread safety
            if (_instance == null)
            {
                lock (_lock)
                {
                    if (_instance == null)
                    {
                        _instance = FindObjectOfType<GameManager>();
                        
                        // If there is no instance in the scene, create a new one
                        if (_instance == null)
                        {
                            GameObject singleton = new GameObject("GameManager");
                            _instance = singleton.AddComponent<GameManager>();
                        }
                    }
                }
            }

            return _instance;
        }
    }

    // Awake method to enforce singleton property
    private void Awake()
    {
        lock (_lock)
        {
            if (_instance == null)
            {
                _instance = this;
                DontDestroyOnLoad(gameObject); // This makes sure the instance is not destroyed on scene load
            }
            else if (_instance != this)
            {
                Destroy(gameObject); // Destroy this instance if another instance already exists
            }
        }
    }

    // Other GameManager methods and properties go here
}

 

 

사용방법

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;

public class SingletonUsing : MonoBehaviour
{
    [FormerlySerializedAs("_Singleton")] public Singleton_PrefabUsing singletonPrefabUsing;
    
    // Start is called before the first frame update
    void Start()
    {
        // _Singleton = GameObject.Find("Singleton").GetComponent<Singleton>();
        singletonPrefabUsing = Singleton_PrefabUsing.Instance;
    }

    // Update is called once per frame
    void Update()
    {
        singletonPrefabUsing.TestFunction();
    }
}

 

'STUDY > 디자인패턴' 카테고리의 다른 글

Command 커맨드 패턴 ★★★  (0) 2024.07.16
chain of responsibility 책임연쇄 패턴  (0) 2024.07.16
Proxy 프록시 패턴  (0) 2024.07.15
Flyweight 플라이웨이트 패턴  (0) 2024.07.15
추상 팩토리 패턴  (0) 2024.07.12