04
12

썸네일

 

유니티를 쓰면서 제일 처음 접한 싱글톤은 간단했다.

 

gameManager에 싱글톤 구현해서 온갖 스크립트에서 참조를 하였다.

 

물론 규모가 커지니까 수습이 안되서 망했다.

 

오늘은 이 싱글톤을 정리 해봐야겠다.

 


#1 그냥 싱글톤

public class gameManager : MonoBehaviour
{
    //instance를 static으로 선언해서 다른 오브젝트에서도 접근 가능
    public static gameManager instance;
    
    public int enemyLeftAmt; //공유할 아무 변수
    
    void Awake()
    {
        if (instance != null) //이미 존재하면
        {
            Destroy(gameObject); //두개 이상이니 삭제
            return;
        }
        instance = this; //자신을 인스턴스로
        DontDestroyOnLoad(gameObject); //씬 이동해도 사라지지않게
    }
}

몇 년동안 쓰다가 습관이 되어버려 프로젝트 규모 신경안쓰고 쓰다가 당했다.

 

위에 코드로 만든 gameManager 스크립트를 그대로 오브젝트 하나에다가 넣어주면

 

다른 오브젝트의 스크립트에서 다음과 같이 접근 가능하다.

public class 다른스크립트 : MonoBehaviour
{
    private void Start()
    {
    	//요런식으로 모두가 gameManager에 접근 가능
        int nowLeftNum = 999999;
        gameManager.instance.enemyLeftAmt = nowLeftNum;
    }
}

gameManager.instance.변수나 함수

 

이런식으로 전역에서 사용가능하다.

 

DontDestroyOnLoad(gameObject)는 씬 이동시 파괴 되지 않게 하기 위함이다.

 


#2 스태틱 필드(Static Field) 싱글톤

┌인스턴스 필드? 스태틱 필드?

더보기

인스턴스 필드(Instance Field) : 클래스 내부에 선언된 일반변수,

new 키워드로 메모리 주소 만들어서 고유한 메모리를 확보함.

 

스태틱 필드(Static Field) : static 키워드로 정의된 변수,

인스턴스 없이도 생성 즉시 메모리에 할당됨.

public class Player : MonoBehaviour {
    public static Player InstanceField;
    public static Player GetInstanceField(){
        return InstanceField;
    }
    public static void SetInstanceField(Player instanceField)
    {
        Player.InstanceField = instanceField;
    }
    void Awake()
    {
        if (InstanceField != null) //이미 존재하면
        {
            Destroy(gameObject); //두개 이상이니 삭제
            return;
        }
        InstanceField = this; //자신을 인스턴스로
        DontDestroyOnLoad(gameObject); //씬 이동해도 사라지지않게
    }
}

굳이 gameManager아니어도 되서 Player 클래스로 적용해보았다.

 

역시나 이경우도 #1그냥 싱글톤처럼 스크립트의 오브젝트가 없어지면 안된다.

 

잊지말고 DontDestroyOnLoad(gameObject)를 넣어주자.

 


#3 프로퍼티(Property) 싱글톤

public class Player : MonoBehaviour {
    private static Player instance;
    public static Player Instance{
        get{
            return instance;
        }
        set{
            instance = value;
        }
    }
}

프로퍼티에 대해서 모르겠다면 이분의 글이 아주 자세하게 나온다. 

 

참고로 C#에서는 자동으로 프로퍼티 구현할 수 있어서 다음과 같이 쓸 수 있다.

public class Player : MonoBehaviour {
    public static Player Instance{ get; set; }
}

위에 프로퍼티 싱글톤이랑 비슷하고 코드의 길이가 짧아져서 깔끔해졌다.

 

그런데 이 기능을 다음과 같이 활용가능하다.

public class Player : MonoBehaviour {
    public static Player Instance{ get; private set; }
}

달라진 점은 private 키워드를 set 속성 접근자 앞에 붙여주었다.

 

이러면 오로지 같은 클래스 내에서만 set으로 변경 가능하다.

 

이러면 전역으로 모두가 접근가능하지만 읽기 전용이 느낌으로 사용 가능하다.

 

프로퍼티 싱글톤도 마찬가지로 선언 후 Awake에서 한번 세팅 해줘야한다.

void Awake()
{
    if (Instance != null) //이미 존재하면
    {
        Destroy(gameObject); //두개 이상이니 삭제
        return;
    }
    Instance = this; //자신을 인스턴스로
    DontDestroyOnLoad(gameObject); //씬 이동해도 사라지지않게
}



번외) 싱글톤 상속 템플릿

 

https://kimyir.tistory.com/113

 

유니티 싱글톤 상속 템플릿

안녕하세요.유니티 싱글톤에 대해서 모르시는 분은 없을거라고 생각합니다.다만 매번 클래스에서 싱글톤을 구현하실 때 코드가 많이 더러워지는데요.이런분들을 위해 싱글톤을 구현한 클래스

kimyir.tistory.com

 

COMMENT