들어가며
이번 글은 모노싱글턴의 코드를 보며 구조 파악 및 사용된 코드에 대해 설명하는 글이다.
싱글턴 -
2024.07.01 - [학교수업/기초수업] - 싱글턴 / UNITY / 학교수업
모노 싱글턴이란?
여러 가지 싱글턴 패턴 중 한 종류이다.
MonoBehaviour를 상속받아야 하는데 싱글턴을 작용시키고 싶은 클래스들에게
싱글턴을 적용시켜 관리해 주는 싱글턴 패턴이다.
모노 싱글턴 코드
(심화반 수업에서 선생님이 짜주신 코드이다. )
public class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance = null;
private static bool IsDestroyed = false;
public static T Instance
{
get
{
if (IsDestroyed)
_instance = null;
if (_instance == null)
{
_instance = GameObject.FindObjectOfType<T>();
if (_instance == null)
Debug.LogError($"{typeof(T).Name} singleton is not exist");
else
IsDestroyed = false;
}
return _instance;
}
}
private void OnDisable()
{
IsDestroyed = true;
}
}
이 코드를 이해하려면 크게 제네릭, 싱글턴, 프로퍼티 정도만 알면 된다.
싱글턴은 따로 정리하였기 때문에 제외하고 나머지를 설명하겠다.
제네릭
T(TYpe)로 사용하고
형식 매개변수라 불린다.
클래스를 일반화를 하는 역할이다.
(일반화란? 데이터 형식을 일반화시켜서 모든 자료형이 사용할 수 있게 만드는 것.)
클래스 이름뒤에 <T>를 붙이면 그 클래스는 일반화 클래스가 돼서
멤버 변수도 일반화 시킬 수 있다.
ex) List <T>, Dictionaray <T, T>, Stack <T> 등
모노 싱글턴 또한 MonoSingleton <클래스이름>로 사용한다.
그러면 내부에 있는 instance의 자료형이 클래스이름으로 된다.
where
제네릭 타입에 대한 제약을 걸 수 있는 코드이다.
모노 싱글턴에서는 받아오는 제네릭이
MonoBehaviour를 상속받는 클래스일 때만 사용이 가능하게 제약을 걸어놓았다.
Property
프로퍼티. 속성이라는 의미를 가지고 있다.
public Vector2 Movement { get; private set; }
위와 같이 사용 한다.
사용하는 이유
클래스의 변수는 정보 은닉을 위해 private를 써야 하지만
다른 스크립트에서 접근하고 싶은 때가 있다.
그러면 public으로 할 수 있지만 은닉성에 어긋나고
다른 곳에서 수정이 가능하기 때문에 좋지 않다.
private Vector2 Move;
public Vector2 GetMove()
{
return Move;
}
public void SetMove(Vector2 move)
{
Move = move;
}
해결법은 위와 같이 get함수와 set 함수를 만드는 것이지만
모든 변수에 적용하면 스크립트가 길어지기 때문에
한 줄로 정의해 둔 것이 프로퍼티이다.
프로퍼티의 get을 통해 값을 가져올 수 도 있고 set을 통해 세팅을 할 수 도 있다.
세팅을 원하지 않는다면 set을 지우면 되고,
다른 클래스에서 세팅을 막고 싶다면 private set을 사용하면 된다.
모노 싱글턴에서의 프로퍼티 역할
public static T Instance
{
get
{
if (IsDestroyed)
_instance = null;
if (_instance == null)
{
_instance = GameObject.FindObjectOfType<T>();
if (_instance == null)
Debug.LogError($"{typeof(T).Name} singleton is not exist");
else
IsDestroyed = false;
}
return _instance;
}
}
모든 클래스 사용이 가능해야 하기 때문에 제네릭형으로 프로퍼티를 선언하고 set은 필요가 없어서 지운다.
코드 구조 설명
Instance에 접근하면
부셔줬는지 안 부셔줬는지 확인 이후 부서졌으면 _instance를 null로 돌려둔다.
(_instance 변수는? 싱글턴의 정보가 들어가 있는 변수이다.
Instance는 _instance에 접근할 때 조건을 걸기 위한 프로퍼티이다.)
이후
접근하려 했을 때 _instance가 null이라면 아래 코드가 호출된다.
_instance = GameObject.FindObjectOfType<T>();
(_instance에 Hierarchy창에서 T형식의 클래스를 찾아 넣는 코드이다)
그래도 null이라면 디버그 로그를 찍는다.
null이 아니라면 IsDestroyed를 false로 바꾸어준다.
마지막으로 _instance를 return 해준다.
모노 싱글턴 적용법
public class GameManager : MonoSingleton<GameManager>
클래스에 모노 싱글턴을 상속하며 T자리에 클래스를 넣어주면 된다.
public static //클래스이름을 쓰면 된다 instance;
private void Awake()
{
if(instance == null)
{
instance = this
}
else
{
Destroy(gameObject);
}
}
이렇게 한다면 이전에 알려줬던 싱글턴 코드를 하나도 쓰지 않아도 싱글턴 적용이 끝난다.
GameManager.Instance.변수or함수
다른 스크립트에서 모노 싱글턴을 사용한 클래스에 접근하려면 위와 같이 싱글턴처럼 사용하면 된다.