본문 바로가기
유니티 공부/Unity

Unity - UI 자동화(Bind, Get)

by 코딩하는 돼징 2023. 2. 21.
반응형

Bind

1. enum

이름들을 enum값으로 설정

enum Buttons
{
    PointButton,
}
enum Texts
{
    PoinText,
    scoreText,
}

enum값 넘겨주는 방법은 Reflection을 이용하면 된다.


2. Reflection 이용해서 enum 넘기기

Reflection은 객체를 X-Ray 기능을 가지고 있다. 이를 통해 형식, 메소드 프로퍼티, 필드, 이벤트등의 정보를 확인할 수 있다.


Relfection 더 자세히 알아보러 가기

 

C# 문법 - Reflection, Attribute

1. Reflection class의 모든 필드의 정보를 가져오는 X-ray와 같은 기능을 가지고 있다. C#에서 모든 객체들은 오브젝트 객체에서 파생되어 나온 것이다. Pig클래스에서 없는 함수가 pig 객체에서 나오는

code-piggy.tistory.com


using.System 상단에 입력

private void Start()
{
   Bind(typeof(Buttons)); // 클래스 타입이 Buttons 애들
   Bind(typeof(Texts)):  // 클래스 타입이 Texts 애들
}

private Bind(Type type){}

3. Buttons 산하에 있는 오브젝트들을 찾아서 연동시켜주기

01 Generic 사용하기

이를 이용하게되면 주어진 T및 Type을 기반으로 바인딩하게 된다.

private void Start()
{
   Bind<Button>(typeof(Buttons)); // 클래스 타입이 Buttons 애들
   Bind<Text>(typeof(Texts)):  // 클래스 타입이 Texts 애들
}

private Bind<T>(Type type){}

02 enum 목록들 추출하기(enum을 string으로 가져오기)

private Bind<T>(Type type)
{
    string[] names = Enum.GetNames(type);
}

03 string으로 변환된 것들을 Dictionary에 넣기

UnityEngine.Object는 유니티에 존재하는 모든 컴포넌트와 오브젝트의 조상(기본) 클래스이다.

그러므로 Object를 이용해서 알아서 변환해서 넣어주면 된다.

 

Button, Text 등등 Type이 여러개이므로 Dictionary로 관리

Dictionary<Type, UnityEngine.Object[]> _objects = new Dictionary<Type, UnityEngine.Object[]>();

Dictionary는 유니티 씬 상에 존재하는 오브젝트들을 로드하고 이를 바인딩하여 보관하는데 사용된다.

예를 들어 Buttons이라는 enum타입이 Key로 사용될 경우 해당 Enum에 정의된 이름에 해당하는 실제 오브젝트들을 배열로 담아 Value로 저장한다.

 


배열을 만들어서 저장할 공간 만들어주기

private Bind<T>(Type type)
{
    string[] names = Enum.GetNames(type);
    UnityEngine.Object[] objects = new UnityEngine.Objects[names.Length]; // names 크기만큼 저장할 공간 만들어주기
    _objects.Add(typeof(T),objects);
}

objects는 Dictionary의 Value들을 담는 배열이다.


배열에 mapping 시켜주기

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

3. 특정 GameObject산하 원하는 종류의 오브젝트 검색하는 유틸 함수 만들기

Util.cs

public static T FindChild<T>(GameObject go, string name = null, bool recursive = false) where T : UnityEngine.Object

go : 최상위 부모

name : 이름을 입력하지 않으면 비교하지 않고 그 타입에만 해당하면 리턴해주도록 한다.

recursive : 하위자식만 찾을 것인지 자식의 자식까지 찾을 것인지


01 go가 null이면 return

if (go == null)
    return null;

02 recursive가 true인 경우

만약 name문자열이 비어있거나 null인 경우 컴포넌트의 이름을 검사하지 않고 그냥 해당 컴포넌트로 반환한다. 그리고 현재 컴포넌트의 이름이 지정한 name과 일치하는지 검사하고 일치하면 해당 컴포넌트를 반환한다.

foreach (T component in go.GetComponentsInChildren<T>())
{
    if (string.IsNullOrEmpty(name) || component.name == name)
        return component;
}

03 recursive가 false인 경우

go 게임 오브젝트의 자식 오브젝트 중에서 name이 지정되지 않았거나 혹은 name과 일치하는 이름을 가진 자식 오브젝트 중에서 T형식의 컴포넌트를 찾아 반환한다. 

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

이때 처음으로 발견되는 해당 조건을 만족하는 컴포넌트를 찾아서 반환하며 만약 조건을 만족하는 컴포넌트가 하나도 없으면 null을 반환한다.


04 FindChild에 where T : UnityEngine.Object 조선을 붙였으므로 Bind함수에도 붙여 준다.

private Bind<T>(Type type) where T : UnityEngine.Object
{
    string[] names = Enum.GetNames(type);
    UnityEngine.Object[] objects = new UnityEngine.Objects[names.Length]; // names 크기만큼 저장할 공간 만들어주기
    _objects.Add(typeof(T),objects);
    
    for(int i = 0; i < names.Length; i++)
    {
        objects[i] = null; 
        Util.FindChild<T>(gameObject,names[i],true);
    }
}

Get

01 Get 메서드

_objects에서 T형식 객체 배열을 찾아서 idx에 해당하는 요소를 반환한다. 

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

02

PlayerController.cs

void Start()
{
    Manager.Resource.Instantiate("UI/UI_Button");
}

03 "Score Text" 이름의 TMP_Text 객체를 찾아 그 객체의 텍스트 내용을 Bind Text로 설정

Texts.ScoreText라는 열거형 멤버를 정수로 형변화하여 해당 인덱스에 해당하는 개체를 가져온다.

 private void Start()
{
    Bind<Button>(typeof(Buttons));
    Bind<TMP_Text>(typeof(Texts));
    Get<TMP_Text>((int)Texts.ScoreText).text = "Bind Text";
}

 

 

 

 

 

 

 

 

 

 

참고 :  본 내용은 MMORPG  PART3 강의를 수강하여 작성하였습니다.

https://www.inflearn.com/course/mmorpg-%EC%9C%A0%EB%8B%88%ED%8B%B0/dashboard

 

 

 

 

 

 

반응형

댓글