[Unity] Unity UI 관리법

Date:     Updated:

카테고리:

태그:

Unity의 UI 관리법

유니티의 UI 관리법은 Canvas를 위에 두고, 그 위에 컴포넌트들을 그리는 방식으로 작동합니다. 이를 UGUI 라고 합니다.

UI를 관리하는 방법은 셀 수 없이 많지만, 저는 이번에 UI마다 컴포넌트를 만들어서 관리하는 방법을 사용하였습니다.

또한, 상속을 이용하여 각 UI들의 성질을 미리 정의 한 후, 캡슐화 하여 모든 버튼들이 캡슐화된 함수를 참조하도록 만들었습니다.

예시는 UI_YesNoDialog 를 가져왔습니다.

UI 컴포넌트 만들기

우선 제가 만든 하이어라키 구조 입니다. 자식으로 달려있는 Button 이나 Text를 찾기 위한 방법으로는 public 필드로 만들어서 드래그 앤 드롭 하기, 또는 GetComponentInChildren을 사용하여 참조를 가져옵니다.

public필드로 모든 객체들을 드래그 앤 드롭 할 시, 객체지향에서 많이 벗어나기 때문에, 저는 GetComponentInChildren으로 전부 찾아주었습니다. 하지만 GetComponentInChildren을 하기 위해서는 Generic 안에 찾아야 할 객체의 타입을 넣어주어야 합니다. 그렇기 때문에 제어가 필요한 UI에 클래스를 만들어 다 붙여주었습니다.

public class UI_YesNoDialog : UI_Popup
{
    #region UI
    private UI_YesNoDialog_Button_Yes buttonYes = null;
    private UI_YesNoDialog_Button_No buttonNo = null;

    private UI_YesNoDialog_Text_Content contentText = null;
    private UI_YesNoDialog_Text_Title titleText = null;

    private UI_YesNoDialog_Image_Background imageBackground = null;
    #endregion

    private Action onYesButtonClickCallback = null;
    private Action onNoButtonClickCallback = null;

    protected override void Awake()
    {
        base.Awake();
        buttonYes = GetComponentInChildren<UI_YesNoDialog_Button_Yes>();
        buttonNo = GetComponentInChildren<UI_YesNoDialog_Button_No>();

        contentText = GetComponentInChildren<UI_YesNoDialog_Text_Content>();
        titleText = GetComponentInChildren<UI_YesNoDialog_Text_Title>();

        imageBackground = GetComponentInChildren<UI_YesNoDialog_Image_Background>();
    }
}

이렇게만 하면, Button 이든 Text 이든 다시 GetComponent를 해야하기 때문에, 그 과정을 줄이고자 상속을 사용하여 중복코드를 제거하였습니다.

상속구조는 UI_Base - UI_SubItem - UI_Button 입니다.

🗅 class UI_YesNoDialog_Button_Yes

public class UI_YesNoDialog_Button_Yes : UI_Button
{

}

🗅 class UI_Button

public class UI_Button : UI_SubItem
{
    protected Button button = null;
    private UnityAction onClickEvent = null;

    protected override void Awake()
    {
        base.Awake();
        button = GetComponent<Button>();
    }
    
    public void SetOnClickEvent(UnityAction _onClickEvent)
    {
        button.onClick.RemoveAllListeners();
        button.onClick.AddListener(PlayButtonClickSound);
        button.onClick.AddListener(_onClickEvent);
    }
}

이런식으로 구현 한 후, ButtonOnClick이벤트를 달고 싶다면 제어하는 UI 스크립트에서 다음과 같이 사용하면 됩니다.

🗅 class UI_YesNoDialog

public class UI_YesNoDialog : UI_Popup
{
    public void Init(string _titleString, string _contentString, Action _onYesButtonClick, Action _onNoButtonClick)
    {
        SetText(_titleString, _contentString);
        SetOnYesButtonClickCallback(_onYesButtonClick);
        SetOnNoButtonClickCallback(_onNoButtonClick);
        SetChildButtonClickEvent();
    }

    public void SetChildButtonClickEvent()
    {
        buttonYes.SetOnClickEvent(OnYesButtonClick);
        buttonNo.SetOnClickEvent(OnNoButtonClick);
    }
}

이런식으로 OnClick이벤트를 달아줄 수 있습니다. 그 외에도 버튼의 색상을 바꾼다던지, 버튼에 사운드를 입힌다던지의 기능들을 UI_Button에서 한번에 관리할 수 있기 때문에, 수정에 용이하다는 장점이 있습니다.

UI_Button을 상속받기만 하고, SetOnClickEvent 만 해준다면 한번의 수정으로 모든 버튼들을 수정할 수 있습니다.

또한, 결합도를 낮추기 위해 위의 스크립트에서 볼 수 있듯이, 모든 버튼이벤트들을 Callback으로 분리해 Init에서 넣어주도록 하였습니다.

실제 사용

실제로 Dialog를 띄우는 코드입니다. Close()Show()UI_Base의 확장 메서드 이므로, 애니메이션을 추가하던지, 다른 작업을 추가하던지 도 확장 가능합니다.

    private void Test_UI_YesNoDialog()
    {
        UI_YesNoDialog dialog = UIManager.Instance.GetOrInstantiateWithPool<UI_YesNoDialog>();
        dialog.Init("YesNoDialog", "YesNoDialog Content", () => { dialog.Close(); }, () => { dialog.Close(); });
        dialog.Show();
    }

Unity 카테고리 내 다른 글 보러가기

댓글 남기기