유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom

2. 유니티 디자인패턴 - 싱글턴 패턴 이해하기

  • 2020. 5. 10. 01:57
  • 공부기록

싱글턴 패턴을 대표적으로 많이 쓰는것이라 다들 기본적인 이해는 있으실겁니다. 전역변수에 올려놓고 어디서든 접근가능한 객체로 만드는 패턴입니다. 다들 익숙하신 내용이니 최대한 간단하게 설명하고 넘어가겠습니다.

장점

싱글턴을 활용하면 한 씬에 있는 오브젝트들이 싱글턴 객체에 접근하여 데이터를 쉽게 공유할수 있습니다. 더 나아가 씬이 바뀌어도 데이터를 유지하며 공유를 계속할수 있습니다. (이 경우엔 유니티의 DontDestroyOnLoad 메소드를 사용해야합니다)

단점

싱글턴을 사용하게 되면 많은 오브젝트들과 연결되어 관리가 복잡해질수 있습니다. 예를 들어 다양한 곳에서 호출하게 되니 싱글턴 객체의 데이터가 언제 어느시점에 바뀌는지 파악하기가 어려울수도 있습니다.

언제 사용할까 - 사용 전

유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom
유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom

using UnityEngine;

[RequireComponent(typeof(AudioSource))]
public class DisableSoundGenerator : MonoBehaviour
{
    public AudioClip sound;

    private AudioSource audioSource;

    private void Start()
    {
        audioSource = GetComponent<AudioSource>();
    }

    private void OnDisable()
    {
        audioSource.clip = sound;
        audioSource.Play();
    }
}

총알이 발사되고 나서 사라질때 사운드를 재생시키는 스크립트를 만들었습니다. 총알이 땅바닥에 떨어진 후 사라지기 직전 (OnDisable(유니티 라이프사이클 참고))에 총알에 함께있는 AudioSource 콤포넌트를 통해 사운드를 재생해야합니다. 하지만...

유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom
유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom

오류가 납니다. 왜냐하면 오브젝트가 사라져서 사운드를 재생시킬 AudioSource 콤포넌트가 없어졌기 때문입니다. 이럴때 싱클턴 패턴을 활용한 오디오 매니저를 활용할 수 있습니다. 

언제 사용할까 - 사용 후

유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom

오디오 매니저를 생성했습니다. 

using UnityEngine;

[RequireComponent(typeof(AudioSource))]
public class AudioManager : MonoBehaviour
{
    public static AudioManager Instance;

    private AudioSource audioSource;

    private void Awake()
    {
        Instance = this;
        audioSource = GetComponent<AudioSource>();
    }

    public void PlaySound(AudioClip clip)
    {
    	Debug.Log("<color=yellow>Sound Play!!</color> : " + clip.name);
        audioSource.PlayOneShot(clip);
    }
}

스태틱으로 Instance 라는 이름의 전역변수를 넣어서 자기 자신을 전역변수에 넣어주었습니다. 여기서 예방문을 추가하거나 씬이 전환될때 사라지지 않도록 하는 돈디스트로이 함수를 추가로 작성해줄수 있습니다. 그리고 이 오디오 매니저를 총알이 사라질때 불러주도록 하겠습니다.

유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom
using UnityEngine;

[RequireComponent(typeof(AudioSource))]
public class DisableSoundGenerator : MonoBehaviour
{
    public AudioClip sound;

    private AudioSource audioSource;

    private void Start()
    {
        audioSource = GetComponent<AudioSource>();
    }

    private void OnDisable()
    {
        AudioManager.Instance.PlaySound(sound);
    }
}

결과는 오디오매니저의 사운드재생 함수를 불렀으므로 오디오매니저의 디버그 로그가 호출되어야 할것입니다. 그럼 사운드가 정상 출력된 것입니다.

유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom
유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom

총알이 사라졌음에도 소리가 재생되었습니다. 이렇게 오브젝트 혹은 어떠한 기능을 관리해주거나 할 때 용이한게 싱글턴 패턴입니다.

한 줄 정리 : 신중하게 전역변수에 올려놓고 어디서든 접근가능한 객체로 만드는 패턴

싱글톤 패턴이란?

오직 하나의 인스턴스만 생성해 재사용하기 위한 소프트웨어 디자인 패턴

싱글톤 오브젝트 : 게임 매니저, 오디오 매니저 등 게임 내에서 유일하게 오직 하나만 존재하는 오브젝트

싱글톤 패턴의 특징 : 오직 한 개의 클래스 인스턴스만을 갖도록 보장하고, 어디서든지 그 인스턴스에 접근이 가능

아래는 유니티에서 사용되는 싱글톤 패턴의 예제이다.

유니티 DontDestroyOnLoad 단점 - yuniti DontDestroyOnLoad danjeom
public class GameManager : MonoBehaviour
{
    public static GameManager instance;

    void Awake()
    {
        if (instance)
        {
            Destroy(gameObject);
            return;
        }
        instance = this;
        DontDestroyOnLoad(gameObject);
    }
}

이런 식으로 구현하면 GameManger 오브젝트는 게임 내부의 모든 곳에서 GameManger.instance로 접근할 수 있고, 중복 없이 오직 하나의 객체로 유지된다.

싱글톤 패턴의 단점 : 싱글톤 인스턴스가 다른 인스턴스들과 많은 데이터를 공유할 경우 다른 클래스 인스턴스들 간에 결합도가 높아져 OCP(Open-Closed-Princple : 개방 폐쇄 원칙)를 어기게 된다. 또한 싱글톤 인스턴스는 게임이 게임이 종료될 때까지 계속해서 메모리를 점유하고 있으므로, 너무 많은 싱글톤 인스턴스의 사용은 게임 최적화에 방해가 된다.