Unity Engine/Unity UI

[유니티] UI Manager

Muru 2023. 11. 30. 19:19

UI_Manager #1

 

 


팝업창을 열어보자.

UIManager 스크립트를 생성하고 UI_Popup도 만들어 base를 상속 시켰다.

 

public class UIManager
{
    private int _order = 0;

    //스택 구조를 사용한다.
    Stack<UI_Popup> _popupStack = new Stack<UI_Popup>();

    //<T> == 이름, string name == 프리팹 이름, T == 스크립트
    public T ShowPopupUI<T>(string name = null) where T : UI_Popup
    {
        if (string.IsNullOrEmpty(name))
            name = typeof(T).Name;

        GameObject go = Managers.Resource.Instantiate($"UI/Popup/{name}");
        T popup = Util.GetOrAddComponent<T>(go);
        _popupStack.Push(popup);

        return popup;
    }
}

팝업창을 열기 위해 T타입으로 ShowPopup<T>를 만들었다.<T>와 string name은 프리팹의 이름이고, T는 스크립트를 의미한다. where T로 UI popup만 받게 할것이다.

 

그리고 IsNullOrEmpty로 이름이 없다면, 타입의 이름 그대로 넣어준다. 리소시스로 팝업창을 열고 컴퍼넌트까지 붙인뒤, Stack의 함수인 Push를 사용해 popup창을 열고 반환했다.

public void ClosePopupUI()
{
        if (_popupStack.Count == 0)
            return;

        UI_Popup popup = _popupStack.Pop();
        Managers.Resource.Destroy(popup.gameObject);
        popup = null;
        _order--;
}

스택을 사용하기때문에 Count가 0이면 return하도록 필히 명시해준다. 그리고 Stack의 함수인 Pop으로 뽑아와주고, 리소스를 제거한다. 만에 하나로 popup도 null로 만들어주며, 처음 선언한 _order의 값을 마이너스해준다. (플러스는 다른곳에서함)

 

 

이제 가볍게 ShowPopupUI해주면 창이 켜질것이다.

 

 

Close해주면 닫기 까지 완료.

 

 

추가로 전체 닫기 기능, 안전하게 닫는 기능까지 추가해주는게 가능하다.


 

UI_Manager #2

 

    private int _order = 10;
    
    public void SetCanvas(GameObject go, bool sort = true)
    {
        Canvas canvas = Util.GetOrAddComponent<Canvas>(go);
        canvas.renderMode = RenderMode.ScreenSpaceOverlay;
        canvas.overrideSorting = true;
        if (sort)
        {
            canvas.sortingOrder = _order;
            _order++;
        }
        else
        {
            canvas.sortingOrder = 0;
        }
    }

 

캔버스 함수를 만들어서 canvas 관리를한다. renderMode는 스크린오버레이, overrideSorting으로 몇개의 캔버스가 생겨도 상관없게 만들어주고, 소팅을 받는다면 _order ++; 아니면 0으로 만든다.

 

여기서 sorting을 안받는 else는 팝업과 관련없는 일반 UI를 의미한다.

 

public class UI_Popup : UI_Base
{
    public virtual void Init()
    {
        Managers.UI.SetCanvas(gameObject, true);
    }
}

============

public class UI_Scene : UI_Base
{
    public virtual void Init()
    {
        Managers.UI.SetCanvas(gameObject, false);
    }
}

또한 캔버스 설정을 위해 초기화를 해준다.

 

이제 완료가 되었는데, 하이어라키 정리가 필요하다. ui팝업이 많이 생성될텐데 정리를 한번 해보자.

 

   기존 ShowPopupUI에서
   
    public T ShowPopupUI<T>(string name = null) where T : UI_Popup
    {
        if (string.IsNullOrEmpty(name))
            name = typeof(T).Name;

        GameObject go = Managers.Resource.Instantiate($"UI/Popup/{name}");
        T popup = Util.GetOrAddComponent<T>(go);
        _popupStack.Push(popup);
        
        //추가할곳
        
        return popup;
    }
    
    ===========
    
	//하이어라키창 정리를 위해 UI_Root오브젝트 생성 및 자식으로 만듦
	GameObject root = GameObject.Find("@UI_Root");
	if (root == null)
		root = new GameObject { name = "@UI_Root" };
        
   		go.transform.SetParent(root.transform);
    
    ===========
를 주석자리에 추가해준다.

이제 깔끔히 정리가 되었다.


 

SceneUI추가


    public T ShowSceneUI<T>(string name = null) where T : UI_Scene
    {
        if (string.IsNullOrEmpty(name))
            name = typeof(T).Name;

        GameObject go = Managers.Resource.Instantiate($"UI/Scene/{name}");
        T sceneUI = Util.GetOrAddComponent<T>(go);
        _sceneUI = sceneUI;

        //하이어라키창 정리를 위해 UI_Root오브젝트 생성 및 자식으로 만듦
        GameObject root = GameObject.Find("@UI_Root");
        if (root == null)
            root = new GameObject { name = "@UI_Root" };

        go.transform.SetParent(root.transform);

        return sceneUI;
    }

씬 창도 추가해야하므로 유사하게 ShowSceneUI를 만들어준다.

그런데 중복된 코드는 싫으므로 @UI_Root 부분을 

public GameObject Root
{
	get
    {
    	GameObject root = GameObject.Find("@UI_Root");
        
        if (root == null)
        	root = new GameObject { name = "@UI_Root: };
            
        return;
    }
}

을 새로 만들어주고 밑에 Root를 넣어주면된다.


 

마지막으로 오버라이딩하며 팝업창을 닫기 편하도록 버츄얼 인터페이스를 만들어주도록하자.