뭔가 소스를 작성하다 보면 어디서든지 접근할 수 있는 하나의 인스턴스만 있는 그런 경우가 있다.
** 예를 들면 데이터를 담당하는 오브젝트같이 하나의 인스턴스만 필요로 하는 Control Class 혹은 Manager Class를 만들어야 하는 일이 발생한다.
그럴 땐 거의 싱글톤 패턴이나, 정적 클래스로 많이 제작을 한다.
-> 이전의 글에서 데이터를 다룰 땐, 정적 클래스로 접근했다.
그러나 싱글톤 패턴과 정적 클래스를 섞어서 쓰면 코드가 더러워진다.
그래서 차이를 알고 적절히 써야한다.
그래서 오늘 이 글을 쓴다.
알아보자
**Unity는 C#을 언어로 쓰지만 싱글톤 사용 시 방식이 조금 다르다.
- 일반 C#에서는 기본 생성자를 사용하지 못하게 private으로 막아야 한다.
- 유니티에서는 Monobehaviour를 상속 받는 클래스가 인스턴스화되는 과정을 그것으로 막을 수 없으니까 Start나 Awake에서 검사해서 막는 방법을 사용한다.
우선 싱글톤의 정의를 알아보자
singleton 패턴은 객체의 생성과 관련된 패턴으로서 특정 클래스의 객체(instance)가 오직 한 개만 존재하도록 보장한다.
객체를 메모리에 한번만 올리는 패턴 즉, 클래스의 객체를 하나로 제한한다.
** 이 인스턴스작성하다 보면 어디서든지 접근할 수 있는 하나의 인스턴스만 있는 그런 경우가 있다.
** 이 인스턴스는 전역에서 접근가능하도록 한다. 이게 보통이다.
언제 사용하느냐????
싱글톤을 쓰는 경우는 여러 곳에서 동일한 상태의 객체를 동시에 접근해야 할 때 , 동일한 자원이나 데이터를 처리하는 객체가 불필요하게 여러 개 만들어질 필요가 없는 경우에 주로 사용한다.
그러면 싱글톤의 특징은 뭘까?
싱글톤을 이용하면 임의의 클래스에서 어디서든 내가 만든 싱글톤 인스턴스를 사용할 수 있다.
DontDestroyOnLoad를 사용하면 씬을 이동해도 사용하던 싱글톤 객체가 유지된다.
다른 스크립트에서 굳이 참조 선언을 안해도 바로 쓸 수 있어서 좋다.
그저 instance property로 접근이 가능하다.
싱글톤은 상속이 가능하다.
또한 인터페이스도 구현이 가능하다.
비동기적으로 초기화도 가능하다. 초기화시점 조절 가능하다는 이야기다.
-> 보통 처음에 초기화하긴 한다.
하지만
싱글톤을 과다하게 쓰면 코드가 너무 방대해지고 코드의 흐름을 알기 어려워져서... 생각하고 써야 한다.
static의 특성 때문에 프로그램 실행도중에 메모리를 내릴 수 없다. 계속 할당된 채로 있다.
-> 힙에 저장된다.
싱글톤 객체를 사용하지 않더라도 일단 메모리에 올려놓기 때문에 사용하지 않는 싱글톤 객체를 메모리에 존재하니까 메모리 낭비가 될 수 있다.
유니티에서 예시를 보자
**싱글톤을 사용하는 것이 이렇게 쓰는 것만은 아니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//유니티에서 달라지는점
// 객체를 컴포넌트화 시켜서 다루는데
// 이미 씬에 배치되어있거나, Prefab에 붙어있는 컴포넌트 Instantiate 되어서 씬에 등장할 수 있다.
// 유일성을 보장하기 위해 다른 조건을 넣어주어야 한다.
public class singletonComponent : MonoBehaviour
{
//static으로 선언하여 모든 SingletonComponent의 객체들이 공유하게됨.
//private으로 선언하여 외부에서 수정을 막음.
private static SingletonComponent instance;
//Instance Property 임.
public static SingletonComponent Instance
{
get
{
//유일성을 위해 이미 선언되었는지 확인하는 작업이다.
if(instnace == null)
{
var obj = FindObjectOfType<SingletonComponent>();
if(obj != null)
{
instance = obj;
}
else
{
var newObj = new GameObject().AddComponent<SingletonComponent>();
instance = newObj;
}
}
return instance;
}
}
//하지만 Instantiate이나 기존 오브젝트에 AddComponent로 SingletonComponent가 여러 개가 되는 경우를 막아야함
void Awake()
{
var objs = FindObjectsOfType<SingletonComponent>();
if(objs.Length != 1) // 이미 싱글톤 객체가 존재한다는 뜻이다.
{
//따라서 이 객체는 생성되어서는 안되며 삭제한다.
Destroy(gameObject);
return;
}
//만약 처음으로 선언하는 것이라면
//씬의 이동에도 종료까지 객체를 유지하여 사용할 수 있게한다.
DontDestroyOnLoad(gameObject);
}
}
참고링크
terms.naver.com/entry.naver?docId=3532960&cid=58528&categoryId=58528
'Game Development, 게임개발 > 개발' 카테고리의 다른 글
델리게이트, Delegates [Unity] (0) | 2021.04.02 |
---|---|
Coroutine,코루틴(IEnumerator, StartCoroutine, yield 등 )에 대한 모든 것 [Unity] (0) | 2021.03.30 |
Namespace, 네임스페이스 [Unity] (0) | 2021.03.29 |
Extension Method, 확장 메서드 [Unity] (0) | 2021.03.29 |
유니티에서 데이터 관리하는 법,How To Handle Data Between Scenes [Unity] (4) | 2021.03.28 |