Game Development, 게임개발/개발

싱글톤의 특징, Singleton [Unity]

게임이 더 좋아 2021. 3. 30. 05:11
반응형
728x170

 

뭔가 소스를 작성하다 보면 어디서든지 접근할 수 있는 하나의 인스턴스만 있는 그런 경우가 있다.

** 예를 들면 데이터를 담당하는 오브젝트같이 하나의 인스턴스만 필요로 하는 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

반응형
그리드형