게임을 개발하다 보면, 전역적으로 접근할 수 있는 데이터 관리 클래스가 필요할 때가 많습니다.
이때 흔히 싱글톤(Singleton) 패턴을 사용하지만, 이렇게 되면 유니티 툴 (Inspector) 에서 데이터를 설정할 수 없는 문제가 발생할 수 있습니다.
왜 이런 문제가 생길까요?
싱글톤으로 클래스를 만든 후, 멤버 변수를 전역으로 접근하려면 static 이어야 하지만, static 변수는 SerializeField 를 사용할 수 없기 때문입니다.
즉, static 변수는 인스펙터에서 설정할 수 없으므로, 유니티 툴에서 값을 조정할 수 없는 문제가 발생합니다.
해결 방법
인스턴스 변수 + Awake()에서 static 변수로 복사 이 문제를 해결하려면 인스턴스 변수([SerializeField])로 값을 저장한 뒤, Awake()에서 static 변수에 할당하는 방식을 사용하면 됩니다.
최적화된 GameData 싱글톤 코드
public class GameData : MonoBehaviour
{
public static GameData Instance { get; private set; }
[SerializeField] private int playerLevel = 1;
[SerializeField] private float playerHealth = 100f;
public static int PlayerLevel { get; private set; }
public static float PlayerHealth { get; private set; }
void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
PlayerLevel = playerLevel;
PlayerHealth = playerHealth;
}
else
{
Destroy(gameObject);
}
}
}
이 방식의 장점
* 유니티 인스펙터에서 데이터 설정 가능 ( [SerializeField] 활용 )
* 게임 실행 후에는 GameData.PlayerLevel 처럼 전역적으로 접근 가능
* 불필요한 static 변수 중복 없이 깔끔한 코드 유지
* 씬이 바뀌어도 DontDestroyOnLoad()로 데이터 유지 가능
다만, Awake() 에서 유니티 Inspector 에서 설정된 값을 멤버 변수에 넣어주는 수고스러움은 존재합니다.
정리
전역 접근을 위해 static을 사용하고 싶다면, Awake() 에서 인스턴스 값을 정적 변수에 저장하는 방식이 가장 적절합니다.
이제 GameData 를 싱글톤으로 유지하면서도, 유니티 인스펙터에서 쉽게 값을 설정하고 관리할 수 있게 되었습니다.
'Unity' 카테고리의 다른 글
FindObjectOfType<T>() 함수 설명 (0) | 2025.03.10 |
---|---|
Unity 에서 Tag 사용시 알아야 할 내용 (1) | 2025.03.10 |
GameObject 와 Transform 의 Find() 에 대해 (0) | 2025.03.10 |
유니티에서 특정 오브젝트 찾기 : 성능 최적화 (0) | 2025.03.09 |
FindWithTag() 와 FindGameObjectsWithTag() (0) | 2025.03.09 |