unity/유니티 초보

Unity - UI 자동화

rimugiri 2024. 4. 4. 00:33
728x90

유니티에서 UI를 작업하는 경우 하이어라키 창에서 object를 일일이 연결해야된다는 번거러운점이 있다 이를 해결하기위해 자동 연결 기능을 구현해 보자

 

1. Bind - C#은 reflection이라는 좋은 기능이 있으므로 이를 활용하여 구성각 요소들을 얻어와 보자

public class GameUI : MonoBehaviour
{
	public void Bind<T>(Type type) where T : UnityEngine.Object
    {
        // enum 에 있는 요소들의 이름을 가져온다
        string[] names = Enum.GetNames(type);
        UnityEngine.Object[] objects = new UnityEngine.Object[names.Length];

        // 이름을 통해 하위 객체에 동일한 이름을 가지고 있는 GameObject의 컴포넌트를 가져온다
        for (int i = 0; i < names.Length; i++)
        {
            if (typeof(T) == typeof(GameObject))
                objects[i] = Utility.FindChild(gameObject, names[i], true);
            else
                objects[i] = Utility.FindChild<T>(gameObject, names[i], true);

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

        _objects.Add(typeof(T), objects);
    }
    public 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;
    }
    void Start()
    {
        Image image = Get<Image>((int)Images.Foreground);
    }

}

 

2. Uility구현 - FindChild 사용을 위한 Utility 구현이다

public static class Utility
{
    public static T FindChild<T>(GameObject go, string name = null, bool recursive = false) where T : UnityEngine.Object
    {
        if (go == null) return null;

        if (recursive)
        {
            foreach (T component in go.GetComponentsInChildren<T>())
            {
                if (component.name == name)
                {
                    return component;
                }
            }
        }
        else
        {
            Transform transform = go.transform.Find(name);
            if (transform != null)
            {
                return transform.GetComponent<T>();
            }
        }
        return null;
    }
    // GameObject는 Copmonent가 아니기 때문에
    public static GameObject FindChild(GameObject go, string name = null, bool recursive = false)
    {
        Transform transform = FindChild<Transform>(go, name, recursive);
        if (transform != null)
            return transform.gameObject;
        return null;
    }
}

이 방식은 몇가지 단점이 있는데

첫번째는 박싱 언박싱이 호출 될때마다 일어난 다는 점과 reflection이 성능상 그렇게 좋지 않다는 점이 있다..

다른 자동화 방법이 있는지 한번 더 알아봐야겠다.

728x90