🐧 들어가기 앞서

게임 구상을 하느라 시간을 다 썼는데, 마땅한 아이디어가 나오지 않아 큰일이다..


🐧 오늘 배운 것

  1. 제네릭 싱글톤

🐧 기억할 것 & 진행

Generic Singleton

이전 포스팅에서 제네릭 싱글톤에 대해 한 번 다룬 적이 있다.

하지만 왜 써야하는지는 적지 못했고, 해당 코드보다 더 마음에 드는 코드를 발견했다.

우리가 흔히 싱글톤을 구현하는 방법은

public class UIManager : MonoBehaviour
{
    private static UIManager instance;
    public static UIManager Instance
    {
    	get
        {
        	if(null == instance)
            {
            	return null;
            }
            return instance;
        }
     }
    

    private void Awake()
    {
        if(instance == null)
        {
            instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else
        {
            Destroy(this.gameObject);
        }
    }
    
    public void Save()
    {
    	// 저장 기능
    }

}
public class Test : MonoBehaviour
{
	void Start()
    {
      UIManager.Instance.Save();
    }
}

Static

그러나 이럴 경우 Static을 쓰면 쓸수록 메모리 누수가 발생한다.

전역 변수와 정적 변수(Static)은 데이터(Data)영역에 저장되는데, 이곳에 저장된 메모리들은 프로그램이 끝날 때 까지 없어지지 않고 계속 남아있기 때문이다.

우리가 매니저를 많이 만들고, Static을 자주 사용할 수록 메모리 낭비가 될 수 있다.
(UIManager, PlayerManager, AudioManager, GameManager...)

https://jygame7130.tistory.com/4

해결 방법?

매니저마다 싱글톤을 만드는 작업은 굉장히 비효율적이다.
또한 협업을 진행할 경우 싱글톤을 만드는 방법이 다 다르다 보니 차라리 컨벤션을 통해
제네릭으로 싱글톤을 만들어 사용하는 것이다.

이것도 커스텀이 굉장히 많이 되기 때문에, 사용자의 입맛에 따라 수정하길 바람!

using UnityEngine;

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T instance;

    public static T Instance
    {
        get
        {
            if (instance == null) // 1
            {
                instance = (T)FindObjectOfType(typeof(T)); // 2

                if(instance == null) // 3
                {
                    GameObject obj = new GameObject(typeof(T).Name, typeof(T));
                    instance = obj.GetComponent<T>();
                }
            }
            return instance;
        }
    }

    public void Awake()
    {
        if (transform.parent != null && transform.root != null) // 5
        {
            DontDestroyOnLoad(this.transform.root.gameObject);
        }
        else
        {
            DontDestroyOnLoad(this.gameObject); // 4
        }
        
    }
}
  • instance null 조건 처리
  1. 만약 인스턴스가 null이라면,
  2. 우선 어딘가에 인스턴스가 있을 수 있으니 인스턴스를 FindObejctofType으로 찾는다.
  3. 찾아봤는데 없다면, 게임 오브젝트를 새로 만든다.
  • DontDestoryOnLoad 처리
  1. DontDestroyOnLoad를 통해 씬이 전환될때도 오브젝트가 파괴되지 않는다.
    그러나 DontSestroyOnLoad가 다른 오브젝트의 하위에 있다면 작동하지 않는다.
  2. 따라서 조건문을 통해 매니저가 부모이거나, 자식일 때 작동할 수 있게 해준다.

호출 방법

public class UIManager : Singleton<UIManager>
{
	public void Game()
    {
    	Debug.Log("UIManager Singleton");
    }
}
public class Test : MonoBehaviour
{
	void Start()
    {
      UIManager.Instance.Game();
    }
}

🐧 내일 할 일

개인 과제 구상 하기!

최종 과제물 아이디어 구상하기!

0개의 댓글