GameManger 같은 전역 클래스가 필요할 경우, 흔히 singleton 패턴을 사용합니다. 그런데 하나의 scene 이 아니라 2개 이상의 scene 에서 GameManager 를 사용하려면, 각 scene 마다 GameManager GameObject 를 hierarchy 창에 생성해야 하는 문제에 부딪히게 됩니다. 이 문제를 깔끔하게 해결하려면 싱글톤 구조를 약간 확장해줄 필요가 있습니다.
Scene 전환이 있을 경우에도 안전한 singleton 패턴
public class GameManager : MonoBehaviour
{
public static GameManager Instance { get; private set; }
void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject); // 중복 인스턴스 제거
return;
}
Instance = this;
DontDestroyOnLoad(gameObject); // 씬 전환 시에도 유지
}
}
이 구조는 다음과 같은 상황에서 안정적으로 작동합니다:
* GameManager 가 첫 번째 scene 에서 한 번만 생성됩니다.
* DontDestroyOnLoad 로 인해 이후 scene 에서도 유지됩니다.
* 두 번째 scene 부터는 중복 생성 시 바로 파괴됩니다.
하지만 문제는 GameManager 가 없는 특정 scene 만 단독으로 실행(Play) 할 경우입니다.
이때는 GameManager 가 존재하지 않기 때문에 NullReferenceException이 발생할 수 있습니다.
Resources 폴더를 통한 GameManager 자동 생성
이 문제를 해결하려면 GameManager 를 사전에 Resources 폴더에 prefab 으로 저장해두고, 코드에서 자동으로 로딩되도록 구성하면 됩니다.
GameManager 프리팹 생성 및 저장
1) Hierarchy에서 GameManager 오브젝트를 생성합니다.
2) Project 창의 Assets/Resources 폴더로 드래그하여 프리팹으로 저장합니다.
3) Hierarchy에 있는 GameManager 오브젝트는 삭제합니다.
GameManager.cs 에 자동 로딩 코드 추가
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void AutoCreateSingleton()
{
if (Instance == null)
{
GameObject prefab = Resources.Load<GameObject>("GameManager");
if (prefab != null)
{
_ = Instantiate(prefab);
}
else
{
Debug.LogError("GameManager 프리팹을 Resources 폴더에서 찾을 수 없습니다.");
}
}
}
이제 어느 씬에서든 GameManager가 존재하지 않으면 자동으로 생성되어 null 참조 문제 없이 안전하게 작동하게 됩니다.
마무리
Scene 이 하나일 때는 단순한 singleton 구조로도 충분하지만, 여러 scene 을 오가는 게임에서는 조금 더 견고한 구조가 필요합니다. Resources 폴더를 활용한 자동 생성 방식은 이러한 문제를 깔끔하게 해결해줄 수 있으며, 프로젝트가 커질수록 유용해집니다.
추가로 ...
만약 GameManager 와 같은 싱글톤 클래스가 scene 마다 초기화해야 할 데이터를 가지고 있다면, Awake() 나 Start() 함수에 의존해서는 안 됩니다. 왜냐하면 씬이 다시 로드되어도 이 함수들은 이미 호출되었기 때문에 다시는 호출되지 않습니다.
이런 경우에는 반드시 SceneManager.sceneLoaded 이벤트를 활용해, 씬이 바뀔 때마다 필요한 데이터를 초기화해주는 구조로 만들어야 합니다. SceneManager.sceneLoaded 에 대해서는 이후에 자세히 다뤄보겠습니다.
'Unity' 카테고리의 다른 글
유니티에서 플레이 모드인지 아닌 헤깔릴 때 (0) | 2025.04.05 |
---|---|
유니티에서 Resources 폴더에 대해 알아보기 (0) | 2025.03.31 |
PlayerPrefs - 데이터를 간단하게 저장하는 방법 (0) | 2025.03.25 |
Button 클릭시, AddListener() 함수로 연결하는 방법 (0) | 2025.03.25 |
Button 클릭 시, 내가 짠 함수를 호출하는 방법 (0) | 2025.03.24 |