[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

+ Recent posts