[Unity] 코드로 오브젝트 매핑하기

Yerin·2023년 7월 21일
0

아래 사진처럼 직접 드래그 앤 드롭으로 오브젝트를 연결하는 것이 아닌
코드로 오브젝트를 연결하려 한다.

리플렉션을 이용하여 enum을 넘겨준다.

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

public class UI_Button : MonoBehaviour
{
    [SerializeField]
    Text _text;

    enum Buttons
    { 
        PointButton
    }


    enum Texts
    { 
        PointText,
        ScoreText
    }
    private void Start()
    {
        Bind(typeof(Buttons));
        Bind(typeof(Texts));
    }
    void Bind(Type type)
    { 
    }

    
}

UI_Button 오브젝트에 위 스크립트가 붙어 있기때문에
해당 오브젝트를 기준으로 자식 오브젝트를 찾아가는 방법을 사용할 것이다.

이때 오브젝트를 찾는 함수는 따로 빼두어 Util.cs라는 이름의 스크립트로 정리한다.

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

public class Util
{
    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;
    }
}

이제 다시 UI_Button 스크립트로 돌아가 아래와 같이 작성하여 마무리한다.

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

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

    enum Buttons
    { 
        PointButton
    }


    enum Texts
    { 
        PointText,
        ScoreText
    }
    private void Start()
    {
        Bind<Button>(typeof(Buttons));
        Bind<Text>(typeof(Texts));
    }
    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++)
        {
            objects[i] = Util.FindChild<T>(gameObject, names[i], true);
        }
    }

}

값 설정은 아래와 같이 진행한다.

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

        Get<Text>((int)Texts.ScoreText).text = "Bind Test";
    }


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;
    }

컴포넌트 형식이 아닌 오브젝트는 어떻게 매핑할까?

UI 버튼 프리펍 아래에 빈 오브젝트인 TestObject를 추가한다.

GameObject 형식 전용의 FindChild를 만들어준다.

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

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

    enum Buttons
    { 
        PointButton
    }


    enum Texts
    { 
        PointText,
        ScoreText
    }

    enum GameObject
    { 
        TestObject,
    }
    private void Start()
    {
        Bind<Button>(typeof(Buttons));
        Bind<Text>(typeof(Texts));

        Get<Text>((int)Texts.ScoreText).text = "Bind Test";
    }
    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);


        }
    }

    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;
    }

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;
    }
profile
재밌는 코딩 공부

2개의 댓글

comment-user-thumbnail
2023년 7월 21일

소중한 정보 감사드립니다!

답글 달기
comment-user-thumbnail
2023년 7월 21일

정말 잘 읽었습니다, 고맙습니다!

답글 달기