Unity3D_MMO - UI 자동화 (1)

k_hyun·2022년 10월 12일
0

Unity_MMO_Project

목록 보기
8/33

UI_Button


버튼을 다음과 같이 구성하였다.

Canvas의 이름은 UI_Button, 버튼 이름은 PointButton, 텍스트 이름은 PointText, ScoreText.

그리고 추가적으로 빈 게임오브젝트를 TestObject로 만들었다.

UI_Base.cs

	// <타입, 타입에 해당하는 객체들>
    protected Dictionary<Type, UnityEngine.Object[]> _objects = new Dictionary<Type, UnityEngine.Object[]>();

    // Dictionary에 Button과 Text 객체를 담는다.
    // _objects[Button] = {PointButton}
    // _objects[Texts] = {PointText, ScoreText}
    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); }

Bind 함수는 UI의 자동화를 위한 함수로, 제네릭 함수로 구현하였다.

게임 오브젝트 또는 오브젝트의 컴포넌트에 접근하기 위해 Util.FindChild 함수를 사용한다.

만약 찾는 것이 존재하지 않는다면 로그를 찍는다.

Get 함수는 딕셔너리 안에서 원하는 컴포넌트에 접근하기 위해 구현하였다.

UI_Button.cs

public class UI_Button : UI_Base
{       
    enum Buttons
    {
        PointButton
    }

    enum Texts
    {
        PointText,
        ScoreText
    }

    enum GameObjects
    {
        TestObject,       
    }

    void Start()
    {
        Bind<Button>(typeof(Buttons));
        Bind<Text>(typeof(Texts));
        Bind<GameObject>(typeof(GameObjects));

        GetText((int)Texts.ScoreText).text = "BIND OKAY";
    }        
}

UI_Button에는 버튼, 텍스트, 그리고 게임오브젝트가 존재한다.

enum을 선언하여 실제 존재하는 오브젝트의 이름을 선언하였다.

이름에 대응하는 오브젝트를 Bind 함수를 통해 연결하였다.

Util.cs

	// 게임오브젝트용
    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
    {
        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;           
    }

게임오브젝트용과 컴포넌트용을 구별하여 만들었다.

T에는 컴포넌트만 들어가지 게임오브젝트가 들어가면 오류가 나기 때문이다.

0개의 댓글