싱글톤 패턴이란 프로그램 상에서 유일하게 하나의 객체만 존재하게끔 하여, 모든 곳에서 이 객체를 사용하게끔 이용하는 것이다.
그런데 Unity의 특성 상 MonoBehavior를 갖고있어야지 컴포넌트로서 update와 같은 행동을 할 수있다.
그래서 일반적인 C#에서의 SingleTone 패턴과는 조금 다른 형태를 하고 있다.
하이러키창에서 Ctrl+Shift+N을 통해 Empty Object를 만들 수 있다.
(우클릭 해서 Create Empty해도 된다.)
그리고 C# Script 파일을 만든 후 Manager 오브젝트의 inspector 창에 드래그로 컴포넌트를 추가하자.
이제 더블클릭으로 Script를 수정해보겠다.
Script를 짜기 전에 Unity 엔진에서 스크립트에 대한 주의점을 먼저 알고 지나가는 것이 좋을 것 같다.
MonoBehavior를 상속하고 있으면 컴포넌트로써 게임 오브젝트에 부착할 수 있다.
게임 오브젝트에 붙으면 게임 오브젝트 아래 각각의 컴포넌트로써 작동하며 Unity에 참조되어 Update같은 메서드가 실행된다.
주의할 점은 GameObject 아래 붙어있어야지 Unity에서 관리하는 것이 아니라, MonoBehavoir를 상속하고 있으면 Unity에서 일단 참조는 하고 있다!
이처럼 Component는 Unity에 의해서 참조되어 GameObject에 붙여지기 때문에 일반적으로 동적 할당하듯이 new를 사용하여 생성할 수 없다.
따라서 일반 클래스를 만들기 위해서는 MonoBehavior 상속을 끊어야한다. 이를 통해 new를 통해서 생성할 수 있지만, Update와 같은 것은 외부 컴포넌트에서 실행을 해야되게끔 된다.
Manager클래스를 만들기 전에 어떤 방식으로 만들지 설계에 대해서 얘기해보겠다.
1. Manager Script는 Manager GameObject의 컴포넌트로만 존재해야 한다. (약속)
2. Manager Component가 붙은 다른 GameObject가 여러개 있어도 반드시 하나만 참조할 수 있어야 한다. (오류 방지)
3. Manager GameObject가 없으면 GameObject를 생성해서 해당 컴포넌트를 붙어야 한다. (무결성)
4. 다른 컴포넌트에서 해당 Manager로 접근하여 이벤트(delegate) 가입을 할 수 있어야 한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Manager : MonoBehaviour
{
private static Manager instance = null;
public static Manager Instance {
get{
InitManager();
return instance;
}
}
private static void InitManager()
{
if(instance == null){
GameObject go = GameObject.Find("Manager");
if(go == null)
{
go = new GameObject("Manager");
go.AddComponent<Manager>();
}
DontDestroyOnLoad(go);
instance = go.GetComponent<Manager>();
}
}
void Start()
{
}
void Update()
{
}
}
위의 싱글톤 패턴은 GameObject의 이름이 유일성이 만족해야 위의 설계가 성립하는데, 다행히 유니티의 경우 GameObject의 이름의 유일성이 지켜진다.
DontDestroyOnLoad는 나중에 Scene이 바꼈다가 돌아와도 삭제되지않고 그대로 삭제 안되고 그대로 있는 것이다.
위의 설계대로라면 Manager GameObject가 없어도 문제없이 Manager Script가 살아있을 것이다.
위와 같이 Manager GameObject를 삭제하고, TestObject와 TestObjectScript를 만들어서 TestObject에 TestObjectSciript를 붙여보자.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestObjectComponent : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Manager manager = Manager.Instance;
}
// Update is called once per frame
void Update()
{
}
}
다음과 같이 Manager Script의 프로퍼티로 manager를 가져오고 Ctrl+p로 게임을 실행해 보자.
그럼 다음과같이 DontDestroyOnLoad안에 Manager GameObject와 아래와 같이 스크립트가 제대로 붙어있는 것을 볼 수 있다.