[UNITY] UI 자동화(1) - 인벤토리 구현
일단 결론부터 말하자면 Scene을 관리하는 Scene 객체에 붙여서, Scene이 로드되면 SceneUI를 불러오는 코드이다. 자동화를 해놓았기 때문에, 코드 한 줄만 작성하면 된다. GameScene.cs using System.Collections;
mainsdev.tistory.com
1편에 이어서 글을 써보고자 한다.
UI_Scene.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UI_Scene : UI_Base
{
public override void Init()
{
Managers.UI.SetCanvas(gameObject, false);
}
}
모든 SceneUI의 부모로 두어 관리를 편하게 하려고 만든 코드이기 때문에 상당히 간단한 것을 볼 수 있다.
UIManager의 SetCanvas 함수를 이용하여 호출한 자식 SceneUI에 Canvas 컴포넌트를 추가해준다.
UI_Inven.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UI_Inven : UI_Scene
{ // 인벤토리를 생성하는 코드
enum GameObjects
{
GridPanel // 인벤토리 프리팹 산하에 있는 GridPanel을 불러오기 위해 Enum으로 저장
}
void Start()
{
Init();
}
public override void Init()
{
base.Init(); // UI_Scene의 Init()을 실행
Bind<GameObject>(typeof(GameObjects)); // 불러올 오브젝트들이 저장된 Enum을 바인드
GameObject gridPanel = Get<GameObject>((int)GameObjects.GridPanel); // 바인드 딕셔너리에 enum의 값을 넣어서 오브젝트를 가져온다.
foreach (Transform child in gridPanel.transform) // 위에서 선언된 enum 안의 객체 이름에 해당하는 객체의 자식을 모두 제거한다.
Managers.Resource.Destroy(child.gameObject);
for (int i = 0; i < 8; i++)
{
GameObject item = Managers.UI.MakeSubItem<UI_Inven_Item>(gridPanel.transform).gameObject;
// 위에서 불러온 GridPanel 객체에 인벤토리에 들어갈 아이템을 생성해준다.
// GridPanel을 parent로 설정해주고, 생성한 객체를 item에 저장한다.
UI_Inven_Item invenItem = item.GetOrAddComponent<UI_Inven_Item>();
// 객체에 UI_Inven_Item 컴포넌트를 붙여주고, 불러온다.
invenItem.SetInfo($"Item {i} 번");
// UI_Inven_Item 에 선언되어있는 SetInfo 함수를 통해 생성한 아이템에 이름을 붙여준다
}
}
void Update()
{
}
}
인벤토리를 생성하는 주요 코드이다.
Scene을 관리하는 GameScene.cs에서 ShowSceneUI<UI_Inven>()을 호출하여 UI_Inven 이름을 가진 prefab을 불러온다.
prefab 산하에 GridPanel에 UI_Scene의 SetCanvas를 통해 Canvas 컴포넌트를 추가해준다.
그 다음, 기존 prefab에 존재하던 GridPanel 산하의 자식들을 지운 뒤, 반복문에 GetOrAddComponent<UI_Inven_Item>()을 통해 UI_Inven_Item 이라는 프리팹으로 아이템을 만들고, 인자로 넣어준 gridPanel.transform을 부모로 지정해주었다.
굳이 지우고 다시 만들 필요는 없지만 만들어둔 코드가 잘 작동하는지 테스트하기 위해 남겨두었다.
UI_Inven_Item.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UI_Inven_Item : UI_Base
{ // 인벤토리 안에 있는 아이템 클래스
enum GameObjects
{
ItemIcon,
ItemNameText,
}
string _name;
void Start()
{
Init();
}
public override void Init()
{
Bind<GameObject>(typeof(GameObjects)); // 위에서 선언한 Enum 타입을 바인드
Get<GameObject>((int)GameObjects.ItemNameText).GetComponent<Text>().text = _name;
// 프리팹에 존재하는 ItemNameText 객체안의 Text 컴포넌트의 text 값을 SetInfo로 받아온 이름으로 설정한다.
Get<GameObject>((int)GameObjects.ItemIcon).BindEvent(PointerEventData => { Debug.Log($"item click! {_name}"); });
// 아이템 아이콘을 클릭 했을 경우 Debug.Log로 출력하는 이벤트 생성
}
public void SetInfo(string name)
{
_name = name; // 아이템 이름 설정
}
}
UI_Inven_Item 프리팹은 2가지 요소로 나뉘어 있는데, 이미지를 담은 ItemIcon, 아이템의 이름을 저장할 ItemNameText로 구성되어 있다. 초기화 함수에서 프리팹의 요소들을 바인드한다.
Get을 통해 각각 요소들을 설정한다.
UI_EventHandler.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class UI_EventHandler : MonoBehaviour, IDragHandler, IPointerClickHandler
{
public Action<PointerEventData> OnClickHandler = null;
public Action<PointerEventData> OnDragHandler = null;
public void OnPointerClick(PointerEventData eventData) // 클릭 했을 경우
{
if (OnClickHandler != null)
OnClickHandler.Invoke(eventData); // 이벤트 함수 실행
}
public void OnDrag(PointerEventData eventData) // 드래그 했을 경우
{
if (OnDragHandler != null)
OnDragHandler.Invoke(eventData); // 이벤트 함수 실행
}
}
드래그와 클릭 이벤트를 처리하기 위해 인터페이스를 상속 받는다.
각각의 이벤트들은 델리게이트를 통해 저장되고, 각 이벤트가 감지될 시, 저장된 이벤트 함수를 실행시킨다.
마치며
이로써 모든 코드들을 살펴 보았는데, 기능들을 나누어 관리를 하여 확실히 유지, 보수에서는 편할 것 같다.
그러나 어떤 역할을 하는지 모르면 상당히 복잡한 코드가 될 것 같다. 다음에는 SceneUI, PopupUI를 이용하여 실제 게임의 UI를 구현해 볼 계획이다.
'UNITY' 카테고리의 다른 글
UNITY - Camera - 마우스 클릭으로 이동하기 (0) | 2024.01.12 |
---|---|
UNITY - ResourceManager (0) | 2024.01.12 |
UNITY - UI 자동화(1) - 인벤토리 구현 (0) | 2024.01.11 |
UNITY - UIManager (2) | 2024.01.11 |
UNITY - Camera - 3인칭 시점(2) (4) | 2024.01.08 |