Chapter 1. 싱글톤
카테고리: Unity Lesson 2
태그: Unity Game Engine
인프런에 있는 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) 오브젝트들 중에서만 찾아준다.
- Find 함수
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에 스크립트를 할당하는 곳
- 📜Managers.cs에서 할당해준다.
📜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 오브젝트가 없다면
ob
j가 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
를 만들어 두도록 하기 위하여.
- 📜Managers.cs의 Start() 함수가 실행되기도 전에 다른 스크립트에서 게임 매니저
Instance
가 아직 없다면 만들자. 있다면 다음과 같은 과정을 무시하고 지나가면 된다. 👉 if (Instance == null)Instance
가 단 하나만 존재할 수 있도록 보장이 된다.Instance
만들기- @Managers라는 오브젝트가 없다면 👉 if (obj == null)
- 직접 만들고 📜Managers.cs 컴포넌트도 붙여주자.
obj = new GameObject { name = "@Managers" }; obj.AddComponent<Managers>();
- 직접 만들고 📜Managers.cs 컴포넌트도 붙여주자.
- “@Managers” 오브젝트가 씬이 변경되도 삭제되지 않고 유지 되도록 안전 장치를 걸어주자. 👉 DontDestroyOnLoad(obj)
- @Managers라는 오브젝트가 없다면 👉 if (obj == null)
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
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글남기기