초고교급 희망

[Unity] UI 자동화 (1) 본문

Game/Unity

[Unity] UI 자동화 (1)

연모링 2023. 7. 19. 21:47
728x90

서론...

[SerializeField] TMP_Text _text;

↑ 위와 같이 유니티 툴에서 직접 해당하는 오브젝트들을 바인딩하게 되면 번거롭다.

툴에서 하지 않고 코드를 통해 바인딩 하는 UI 자동화에 대해 배워보겠습니다.

 

 

UI_Base.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UI_Base : MonoBehaviour
{
    protected Dictionary<Type, UnityEngine.Object[]> _objects = new Dictionary<Type, UnityEngine.Object[]>();

    protected void Bind<T>(Type type) where T : UnityEngine.Object
    {
        string[] names = Enum.GetNames(type);
        UnityEngine.Object[] objects = new UnityEngine.Object[names.Length];
        _objects.Add(typeof(T), objects);

        for (int i = 0; i < names.Length; i++)
        {
            if (typeof(T) == typeof(GameObject))
                objects[i] = Util.FindChild(gameObject, names[i], true);
            else
                objects[i] = Util.FindChild<T>(gameObject, names[i], true);

            if (objects[i] == null)
            {
                Debug.Log($"Failed to bind({names[i]})");
            }
        }
    }

    protected T Get<T>(int idx) where T : UnityEngine.Object
    {
        UnityEngine.Object[] objects = null;
        if (_objects.TryGetValue(typeof(T), out objects) == false)
            return null;

        return objects[idx] as T;
    }  

    protected Text GetText(int idx) { return Get<Text>(idx); }
    protected Button GetButton(int idx) { return Get<Button>(idx); }
    protected Image GetImage(int idx) { return Get<Image>(idx); }
}

 

Util.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Util 
{
    public static GameObject FindChild(GameObject go, string name = null, bool recursive = false) 
    {
        Transform transform = FindChild<Transform>(go, name, recursive);
        if (transform == null)
            return null;

        return transform.gameObject;
    }

    public static T FindChild<T>(GameObject go, string name = null, bool recursive = false) where T: UnityEngine.Object // UnityEngine.Object인것만 찾겠다
    {
        if (go == null)
            return null;

        if(recursive == false) 
        {
            for(int i = 0; i < go.transform.childCount; i++)
            {
                Transform transform = go.transform.GetChild(i);
                if(string.IsNullOrEmpty(name)|| transform.name == name)
                {
                    T component = transform.GetComponent<T>();
                    if (component != null)
                        return component;
                }
            }
        }
        else 
        {
            foreach (T component in go.GetComponentsInChildren<T>())
            {
                if(string.IsNullOrEmpty(name) || component.name == name)
                {
                    return component;
                }
            }
        }
        return null;
    }
}

 

FindChild 함수에서 go는 최상위 부모
이름을 입력하지 않았을 때, 타입에만 해당하면 리턴해줌
재귀적으로 찾을 것인지?는 자식의 자식도 찾는다는 뜻
 

T에는 버튼이라든가 텍스트라든가 우리가 찾고싶은 컴포넌트를 넣어주게 된다.

 

UI_Button.cs (사용 예시)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using System;

public class UI_Button : UI_Base
{
    enum Buttons
    {
        PointButton
    }
    
    enum Texts
    {
        PointText,
        ScoreText
    }

    enum GameObjects
    {
        TestObjects, 
    }
    
    private void Start()
    {
        Bind<Button>(typeof(Buttons));
        Bind<TMP_Text>(typeof(Texts));
        Bind<GameObject>(typeof(GameObjects));
        Get<TMP_Text>((int)Texts.ScoreText).text = "Bind Test";
    }
}

 

실행 결과

 

<출처>

인프런 루키스 선생님의 [C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] 를 듣고 정리한 내용입니다.^^

사실 작년에 학교 친구들이랑 들었던 인강인데 이 부분은 뭔가 마음에 와닿지 않아서...

재탕도 아니고 삼탕하다가 이번엔 포스팅을 한 번 해봤습니다.람쥐

 

그냥 궁금한 점

reflection에 대해서 검색해보니까 상당히 고비용의 작업이라서 웬만하면 안 쓰는게 좋다고 하던데...

이렇게 리플렉션 써도 되는건지...?

지나가던 고수 선생님들 계시다면 댓글 부탁드립니다.

728x90