유니티 뼈대 작업(MonoBehaviour/Manager/Singleton)

개발조하·2023년 11월 21일
0

Unity

목록 보기
1/30
post-thumbnail

1. MonoBehaviour

  • 상속 관계

MonoBehaviour ← Behaviour ← Component ← Object

⇒ 즉, MonoBehaviour를 상속받는 모든 스크립트는 GameObject에 붙을 수 있다!!

2. Manager 만들기

  • Managers에 들어가는 것들

UI, Sound, Network, Scene관리 …. 많은 것들이 들어감.

  • Manager 사용 방식

Manager는 관리용 스크립트일 뿐 GameObject에 붙어서 실행시키는 것이 아니다! 그래서 MonoBehaviour의 상속을 받을 필요가 없다.

⚠️ 그렇다고 MonoBehaviour 상속을 지우면, Start(), Update()함수 실행이 안된다;;;;

💡그냥 MonoBehaviour 상속을 유지하고, 하이어라키창에서 빈게임오브젝트(좌표reset) 생성해서 스크립트를 붙여주고 실행한다.

3. Singleton

3.1 Singleton이란?

: 객체의 인스턴스를 한개만 생성되게 하는 패턴.
: 주로 프로그램 내에서 하나로 공유를 해야하는 객체가 존재할 때 해당 객체를 싱글톤으로 구현하여 모든 유저 또는 프로그램들이 해당 객체를 공유하며 사용하도록 할 때 사용된다.

  • 프로그램 내에서 하나의 객체만 존재해야 할 때
  • 프로그램 내에서 여러 부분에서 해당 객체를 공유하여 사용해야 할 때

💡 싱글톤 패턴을 사용하는 이유

  1. 메모리 측면의 이점
    한 개의 인스턴스만을 고정 메모리에 생성하고 추가 생성하지 않기 때문에 추후 해당 메모리에 접근할 때 메모리 낭비를 방지할 수 있다.

  2. 속도 측면의 이점
    생성된 인스턴스를 사용할 때는 이미 생성된 인스턴스를 활용하기 때문에 속도에서도 이점이 있다.

  3. 데이터 공유가 쉽다
    전역으로 사용하는 인스턴스이기 때문에 다른 여러 클래스에서 데이터를 공유하며 사용할 수 있다. 하지만 동시성 문제가 발생할 수 있어 이 점은 유의하여 설계해야 함.

3.2 Singleton 사용하기

  • Player스크립트에서 Managers의 데이터를 사용하려면, Player가 실행될 때 @Managers 오브젝트에 있는 Managers 스크립트를 가져오도록 아래와 같은 코드를 만들어줘야 한다.
    ㄴ 단, 이렇게 Player가 실행될 때마다 Find()함수로 객체를 찾으면 성능 부하가 생기기 때문에 매우 좋지 않다;;

💡Managers를 Singleton으로 단일화시켜 사용한다.
ㄴ하지만 이렇게 Instance = this;로 자기 자신을 Instance에 넣어서 초기화해준다면, @Managers가 한 개 밖에 없을 때에는 문제가 없지만, 만약 누군가 하이어라키에서 Managers 스크립트가 있는 @Managers 오브젝트를 @Managers(1),(2).. 복사해버렸다면, 모두 각자 자신을 Instance로 초기화하는 문제가 발생한다. 이에, 사용할 @Managers로만 초기화되도록 아래와 같이 작성한다.

  • 다른 객체에서 singleton으로 만든 Managers를 불러올 때
    ㄴ GetInstance()함수 하나면 끝!

⚠️ 하지만, 만약 @Managers 객체가 없다면? 이 코드에는 문제가 발생한다!!
그래서, Init()함수로 초기화 상태를 설정해준다. null체크를 통해 s_instance가 아직 없다면 @Managers를 찾고, 만약 해당 객체가 없다면 직접 만들고 Managers 컴포넌트까지 추가한 후, 해당 컴포넌트를 s_instance에 넣어준다!

public class Managers : MonoBehaviour
{
    static Managers s_instance; //유일성이 보장된다.

    public static Managers Instance { get { Init();  return s_instance; } } 
    //외부에서 사용할 때 유일한 매니저를 갖고 온다.
    //다른 오브젝트에서 먼저 Instance로 Managers 객체를 생성해도 null인 경우 체크해서 새로 만들어서 return해줌

    void Start()
    {
        //만약 운좋게 Start()가 실행되면 Init()실행
        Init();
    }

    static void Init() //초기화
    {
        if(s_instance == null)
        {
            GameObject go = GameObject.Find("@Managers");
            if(go == null)
            {
                //하이어라키에 코드로 오브젝트만들고 스크립트 넣음
                go = new GameObject { name = "@Managers" };
                go.AddComponent<Managers>();
            }

            DontDestroyOnLoad(go);
            s_instance = go.GetComponent<Managers>();
        }
    }
}

ㄴ원래는 외부에서 사용할 때 GetInstace()라는 함수로 불러오도록 했는데, 함수로 불러오는게 괄호때문에 괜히 번거로우니까 Instance 프로퍼티로 만들어줬다.

  • 이 코드 한 줄이면 Managers를 불러와 사용할 수 있다!!
public class Player : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Managers mg = Managers.Instance;
    }

}

📄참고자료
C#과 유니티로 만드는 MMORPG 게임_Rookies(인프런)
싱글톤

profile
Unity 개발자 취준생의 개발로그, Slow and steady wins the race !

0개의 댓글