생각났다! 뭐였더라?
오늘은 챌린지 세션에서 튜터님이 해주신 말씀이 너무 와 닿았다.
"기능만 구현하고 나중에 포트폴리오를 쓰려고 하면 의외로 쓸 게 없어요."
이젠 어떻게 구조를 잡을 것인지 생각하면서 코딩하는 연습을 해야 할 때가 온 것이겠지...
ui 자동화 첫 걸음
이제껏 모든 UI 관련을 [SerializeField] 나 public 으로 Inspector 상에서 드래그 드롭 방식으로 연결해 줬었다...
혼자 작업할 땐 혼자 하고 그냥 당장 내가 편하니까 이런 방식을 고수해왔었지만 이제 이 방식도 졸업해야겠지.
어휴 어지럽다;;;
동적 생성과, UI 자동화를 위해 새로운 방법을 써보자.
UI_Base 클래스와 Bind / Get 그리고 Type
UI_Base 클래스는 모든 UI 가 상속받을 부모 클래스이다.
이 클래스에서 UI 생성 시, 모든 UI 컴포넌트를 Dictionary 로 바인드 하고 원할 때 쓸 수 있다.
그 기능을 하기 위해서 다음과 같은 기능들을 살펴보자
Bind
UI가 생성 될 때, 가지고 있길 원하는 컴포넌트들을 내부적으로 Dictionary에 저장하는 함수.
Dictionary<Type, UnityEngine.Object[]> _objects = new Dictionary<Type, UnityEngine.Object[]>();
void Bind<T>(Type type) where T : UnityEngine.Object // Enum의 Type을 넘겨주면 Enum안의 모든 Name과 같은 자식 오브젝트들을 검색, T 타입을 찾아 _objects에 Type키에 저장
{
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++)
{
// gameObject의 자식을 전부 검사, 오브젝트 이름이 names[i]와 일치하면 T 타입을 반환.
// 자세한 코드는 다음 TIL에서
objects[i] = Util.FindChild<T>(gameObject, names[i], true);
if (objects[i] == null)
Debug.Log($"Failed to bind({names[i]})");
}
}
- 저장하고자 하는 타입 T를 넘긴다. 단, T는 UnityEngine.Object를 상속받는 타입만 해당된다.
- Enum을 Type으로 변환 후 매개변수로 받아 Enum에 있는 요소들을 GetNames(type) 으로 string 배열에 담는다.
- Dictionary에 저장 할 값 UnityEngine.Object[] 배열 objects를 names의 길이만큼 만든다.
- Dictionary _objects 에 T 의 Type 을 "Key" 로, 위에서 만든 objects를 값으로 추가한다.
- objects[i] 에 자기 자신의 자식들 중 names[i] 와 같은 이름을 가진 오브젝트에서 T 타입을 할당한다.
그렇다면 Bind 시 실제로 넘겨주는 Type 매개변수는 어떻게 넘길까?
enum Buttons
{
Login_Btn,
SignUp_Btn,
}
UI_Base 를 상속받은 실제로 씬에서 쓰일 UI_Login 클래스 내부에 바인드 하고자 하는
클래스와 비슷하게 enum 을 만들고 (이름은 상관없지만 알기 쉽도록)
실제 찾고자 하는 오브젝트와 동일한 이름으로 만들어 준다.
그 후
public class UI_Login : UI_Base
{
enum Buttons
{
Login_Btn,
SignUp_Btn,
}
public override void Init()
{
Bind<Button>(typeof(Buttons));
}
}
UI_Base 에서 생성 시 실행되는 Init 함수에 Bind 함수를 호출해 바인드를 원하는 타입의 클래스와 enum Type을 넘겨준다.
즉 실제로 쓰일 UI 오브젝트들은 모두 UI_Base 를 상속받은 오브젝트와 동일한 이름의 클래스를 가진다.
UI_Login 이 클래스 명이면 오브젝트 이름도 UI_Login 이다. (나중에 Instantiate 를 위해 맞출 필요가 있음.)
이렇게 Bind 함수를 호출하면 원하는 타입의 클래스가 _objects Dictionary 에 저장이 된다.
Get
바인드 된 타입중 원하는 값을 꺼내쓰는 함수
protected T Get<T>(int index) where T : UnityEngine.Object // Enum의 index를 넘겨주면 T Type키의 index번째 Object를 T 타입으로 캐스팅하여 반환
{
UnityEngine.Object[] objs;
if (_objects.TryGetValue(typeof(T), out objs) == false)
return null;
return objs[index] as T;
}
- 쓰고자 하는 타입 T를 넘긴다.
- 매개변수로 int index 를 넘긴다
- 저장되어있는 typeof(T) 키에 UnityEngine.Object[] 값이 없으면 return null
- 값이 있으면 objs[index] 값을 T 로 캐스팅 하여 반환한다.
이렇게 하면 원하는 타입에 바로 접근이 가능하다.
Get<Button>((int)Buttons.Login_Btn).onClick.AddListener(Login);
요런 식으로
'스파르타 내배캠' 카테고리의 다른 글
스파르타 내배캠 Unity 3기 34일차 (1) | 2024.02.08 |
---|---|
스파르타 내배캠 Unity 3기 33일차 (1) | 2024.02.07 |
스파르타 내배캠 Unity 3기 31일차 (0) | 2024.02.05 |
스파르타 내배캠 Unity 3기 30일차 (0) | 2024.02.02 |
스파르타 내배캠 Unity 3기 29일차 (0) | 2024.02.01 |