Chapter 1. 싱글톤

Date:     Updated:

카테고리:

태그:

인프런에 있는 Rookiss님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part3: 유니티 엔진 강의를 듣고 정리한 필기입니다. 😀
🌜 강의 들으러 가기 Click

🙋‍♀️ 게임 매니저

  • 전역으로 게임 전체를 관리하는 스크립트로 만든 것.
  • 사실 게임 매니저는 컴포넌트로서 어떤 오브젝트에 꼭 붙어야 하는 이유는 없지만 실체는 없지만 Scene에 존재하긴 하는 빈 오브젝트를 만들어서 매니저 스크립트를 컴포넌트로서 붙이고 사용하는 것을 권장한다.
    • 매니저 스크립트를 붙일 용도의 빈 오브젝트를 만들자.


🙋‍♀️ 싱글톤

게임 매니저 스크립트가 붙은 오브젝트 가져오기

현재 “@Managers” 라는 빈 오브젝트에 게임 매니저로 쓸 Managers 라는 C# 스크립트를 붙여준 상태.

📜Player.cs

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

public class Player : MonoBehaviour
{
    void Start()
    {
        GameObject obj = GameObject.Find("@Managers");
        Managers mag = obj.GetComponent<Managers>();
    }

    void Update()
    {
        
    }
}
  • obj 👉 현재 씬에 존재하는 오브젝트(GameObject)들 中에서 이름이 “@Managers”인 오브젝트.
    • Find 함수
      • GameObject 타입의 함수로서 클래스 함수라 GameObject.Find(String) 식으로 사용 된다. 현재 씬에서 인수와 일치하는 이름을 가진 오브젝트를 찾아 리턴해준다.
      • 단, 활성화 되어있는(Active) 오브젝트들 중에서만 찾아준다.
  • mag 👉 obj 오브젝트의 Managers 컴포넌트를 mag에 담았다.
    • C# 스크립트도 컴포넌트다.
    • 즉, @Managers 오브젝트의 Managers 스크립트를 참조하게 된다.


싱글톤 구현하기

게임 매니저는 게임 전반을 관리하기 때문에 게임 매니저 스크립트는 딱 하나만 static으로 만들어 두고 여러 곳에서 이 동일한 인스턴스를 참조한다.

  • 게임 매니저 오브젝트의 스크립트 컴포넌트를 여러 곳에서 공유할 수 있도록 static 으로 만들어 둔다.
  • 단 하나만 존재하는 이 게임 매니저 컴포넌트를 리턴 받을 수 있는 static 함수를 만들어 둔다.
    • 다른 곳에서 사용할 수 있도록 public이어야 한다.


첫번째 방법

📜Managers.cs

게임 매니저로서 동작할 스크립트

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

public class Managers : MonoBehaviour
{
    static Managers Instance;  // 유일성이 보장된다.
    public static Managers GetInstance() { return Instance; }  // 유일한 매니저를 갖고 온다.

    void Start()
    {
        GameObject obj = GameObject.Find("@Managers");
        Instance = obj.GetComponent<Managers>();   // Instance에 스크립트를 할당하는 곳
    }

    void Update()
    {
        
    }
}
  • 싱글톤으로 만들 대상은 “@Managers” 오브젝트에 붙어 있는 📜Managers.cs
    • 여러 곳에서 동일한 인스턴스에 대해 공유할 수 있도록 static으로 선언한다.
      • static Managers Instance
    • 여러 곳에서 동일한 인스턴스를 리턴받아 사용할 수 있도록 이 인스턴스를 리턴하는 static public 함수를 만들어둔다.
      • 클래스 함수가 되므로 다른 여러 곳에서 클래스이름.GetInstance() 로 사용할 수 있게 된다.
  • Instance에 📜Managers.cs 할당하는 것을 딱 한군데에서만 해주면 단 하나만 존재하는게 보장된다.
    • 📜Managers.cs에서 할당해준다.
          GameObject obj = GameObject.Find("@Managers");
          Instance = obj.GetComponent<Managers>();   // Instance에 스크립트를 할당하는 곳 
      
📜Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    void Start()
    {
        Managers mag = Managers.GetInstance();  // Instance 리턴 받아 사용
    }

    void Update()
    {
        
    }
}
  • “@Managers” 오브젝트에 붙어 있는 📜Managers.cs가 할당 되어 있는 Instance를 가져와 사용하면 된다.
    • Managers.GetInstance()
이 방법의 문제점
  • 만약 @Managers 오브젝트가 없다면 obj가 null이 된다.
    • 이런 경우 코드롤 통하여 @Managers 오브젝트를 만들어 주자.
  • @Managers가 있긴 있어도 📜Managers.cs 가 붙어있지 않다면 Instance 가 null이 된다.
    • 이런 경우 코드롤 통하여 @Managers 오브젝트에 📜Managers.cs 컴포넌트를 붙여주자.


두 번째 방법 : 개선

📜Managers.cs

게임 매니저로서 동작할 스크립트

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

public class Managers : MonoBehaviour
{
    static Managers Instance;  // 유일성이 보장된다.
    public static Managers GetInstance() // 유일한 매니저를 갖고 온다.
    {
        Init();
        return Instance;
    }  

    void Start()
    {
        Init();
    }

    void Update()
    {
        
    }

    static void Init()
    {
        if (Instance == null)
        {
            GameObject obj = GameObject.Find("@Managers");
            if (obj == null)
            {
                obj = new GameObject { name = "@Managers" };
                obj.AddComponent<Managers>();
            }

            DontDestroyOnLoad(obj);
            Instance = obj.GetComponent<Managers>();
        }
    }
}
  • GetInstance(), Start() 두 함수에서 Init()을 호출하는 이유
    • 📜Managers.cs의 Start() 함수가 실행되기도 전에 다른 스크립트에서 게임 매니저 Instance를 사용해야 할 일이 생긴다면 먼저 그 곳에서 Instance를 만들어 두도록 하기 위하여.
  • Instance가 아직 없다면 만들자. 있다면 다음과 같은 과정을 무시하고 지나가면 된다. 👉 if (Instance == null)
    • Instance가 단 하나만 존재할 수 있도록 보장이 된다.
    • Instance 만들기
      • @Managers라는 오브젝트가 없다면 👉 if (obj == null)
        • 직접 만들고 📜Managers.cs 컴포넌트도 붙여주자.
          obj = new GameObject { name = "@Managers" };
          obj.AddComponent<Managers>();
          
      • “@Managers” 오브젝트가 씬이 변경되도 삭제되지 않고 유지 되도록 안전 장치를 걸어주자. 👉 DontDestroyOnLoad(obj)
    • Instance에 “@Managers” 오브젝트에 붙어 있는 📜Managers.cs 가져오기
📜Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    void Start()
    {
        Managers mag = Managers.GetInstance();
    }

    void Update()
    {
        
    }
}


세 번째 방법 : 프로퍼티 사용

📜Managers.cs

게임 매니저로서 동작할 스크립트

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

public class Managers : MonoBehaviour
{
    static Managers s_instace;  
    public static Managers Instance
    {
        get
        {
            Init();
            return s_instace;
        }
    }

    void Start()
    {
        Init();
    }

    void Update()
    {
        
    }

    static void Init()
    {
        if (s_instace == null)
        {
            GameObject obj = GameObject.Find("@Managers");
            if (obj == null)
            {
                obj = new GameObject { name = "@Managers" };
                obj.AddComponent<Managers>();
            }

            DontDestroyOnLoad(obj);
            s_instace = obj.GetComponent<Managers>();
        }
    }
}

GetInstance() 함수를 프로퍼티로 바꿔주었다.

📜Player.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    void Start()
    {
        Managers mag = Managers.Instance;
    }

    void Update()
    {
        
    }
}

  • Managers mag = Managers.Instance


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

댓글남기기