Unity 내일배움캠프 TIL 1113 | 재사용 Tab UI 구현하기 | 오브젝트 풀링

cheeseonrose·2023년 11월 13일
0

Unity 내일배움캠프

목록 보기
77/89
post-thumbnail

💡 Tab UI

최종 프로젝트에서 인벤토리 UI 부분을 담당하였다.

3개의 탭을 가진 형태인데 탭 UI 구현은 처음이라 이것저것 레퍼런스를 찾아봤는데, 미리 3개의 탭을 각각 만들고 탭 클릭에 따라 sorting order를 바꿔주는 등의 방식으로 보여주는 경우가 많았다.

하지만 나는 어떤 인간인가
귀차니즘에 지배당한 인간이다.

같은 UI를 사용하는데 3개를 따로 만들어야 하나???? 어우 귀찮아

그래서 튜터님을 찾아가 조언을 구한 결과, 하나의 UI를 3개의 탭이 공유하고 그 안의 슬롯들은 오브젝트 풀링 기법을 사용하여 구현하기로 했다.



⛄ UI_Tab

  • 우선 Tab마다 UI_Tab 스크립트를 연결해주고 클릭 이벤트를 선언해줬다.
public class UI_InventoryTab : UI_Base
{
    public event Action<InventoryType> OnClicked;

    public InventoryType type;
    [SerializeField] private Sprite _selectedSprite;
    [SerializeField] private Sprite _unselectedSprite;
    [SerializeField] private Image _tabImage;

    public void SetTabSelectedState(bool IsSelected)
    {
        if (IsSelected) _tabImage.sprite = _selectedSprite;
        else _tabImage.sprite = _unselectedSprite;
    }

    public void CallOnTabClicked()
    {
        OnClicked?.Invoke(type);
        SetTabSelectedState(true);
    }
}
  • 각 탭은 자신이 가리키는 인벤토리의 타입 값을 가지며, 클릭 이벤트가 발생하면 해당 타입을 넘겨준다.
  • 각 탭은 자신의 상태에 따라 Sprite를 변경한다.
    현재 어떤 탭이 선택되었는지 구분하기 위함이다.



🍠 UI_Inventory

// UI가 처음 생성됐을 때 Tab 리스트 초기 설정
private void InitTab()
{
	for (int i = 0; i < TabList.Length; i++)
    {
    	TabList[i].SetTabSelectedState(false);                     // 모든 탭 unselected 상태로 변경
        TabList[i].OnClicked += ChangeTab;                         // 탭 클릭 이벤트에 UI의 탭 변경 메서드 연결
        TabList[i].OnClicked += _controller.ChangeInventoryType;   // 탭 클릭 이벤트에 컨트롤러의 탭 변경 메서드 연결
    }
    TabList[0].SetTabSelectedState(true)						   // 첫 번째 탭 선택
}
  • UI가 처음 생성되었을 때 Tab들의 초기 설정을 한다.
    Tab 리스트가 public인 이유는..튜토리얼에서 Tab이 필요해서 바꾼 것이니 대충 흐린 눈 하자
  • 탭이 변경 되었을 때의 메서드와 컨트롤러가 들고 있는 인벤토리 타입을 바꿔주는 메서드를 연결했다.
    • ✅ 이 부분도 리팩토링 과정에서 View는 Controller의 존재를 아예 모르도록 변경하면서 수정할 예정이다!
  • 초기에는 첫 번째 탭이 선택되도록 한다.

// 탭 변경 메서드
private void ChangeTab(InventoryType type)
{   
	// 스크롤 뷰 맨 위로 이동
    // 이전에 선택되어 있던 탭을 unselected 상태로 변경 후 현재 선택된 탭의 타입으로 인벤토리 타입 변경
    _scrollViewContainer.anchoredPosition = new Vector3(_scrollViewRectPosition, 0, 0);
    TabList[(int)_curSelectedInventory].SetTabSelectedState(false);
    _curSelectedInventory = type;
}
  • UI_Tab의 클릭 이벤트에 연결되어, 탭이 클릭되면 해당 탭의 인벤토리 타입을 받아온다.
  • 현재 선택된 탭을 선택 해제 상태로 변경하고, 현재 인벤토리 타입도 변경한다.
  • 탭이 변경되었을 때 스크롤 한 것도 원래 상태로 돌려놓는다.



🛷 오브젝트 풀 기법을 활용한 슬롯 생성

// 슬롯 초기화
private void InitSlots(int dataCnt)
{
	// TODO PoolManager 활용해서 리팩토링
    
    int slotCnt = _scrollViewContainer.childCount;          // 전체 슬롯 개수 (스크롤 뷰 자식에 존재하는 슬롯 프리팹 수)
    
    // 슬롯 수가 아이템 수보다 적을 경우
    if (slotCnt < dataCnt)
    {
    	// 리소스 폴더에서 슬롯 프리팹 생성 
        for (int i = 0; i < (dataCnt - slotCnt); i++)
        {
        	GameObject go = Instantiate(Resources.Load<GameObject>("Prefabs/UI/UI_InventorySlot"));
            go.transform.SetParent(_scrollViewContainer);
            go.transform.localScale = Vector3.one;
        }
        slotCnt = _scrollViewContainer.childCount;
    }
    
    // 슬롯 리스트 초기화
    _slotList = new UI_InventorySlot[dataCnt];
    for (int i = 0; i < dataCnt; i++)
    {
    	GameObject go = _scrollViewContainer.GetChild(i).gameObject;
        go.SetActive(true);
        _slotList[i] = go.GetComponent<UI_InventorySlot>();
        
        // 슬롯 내용 설정
        ...
    }
    
    // 여분의 슬롯 오브젝트는 비활성화
    for (int i = dataCnt; i < slotCnt; i++)
    {
    	GameObject go = _scrollViewContainer.GetChild(i).gameObject;
        go.SetActive(false);
    }
}
  • 우선 현재 탭의 데이터 개수를 받아온 뒤, 스크롤 뷰 컨테이너 안에 이미 존재하는 슬롯의 개수와 비교한다.
  • 데이터 수가 더 많다면 리소스 폴더에서 추가로 슬롯 프리팹을 로드한다.
  • 컨테이너 하위 슬롯의 처음부터 데이터 수만큼 슬롯들의 내용을 설정해주고, 사용하지 않는 여분의 슬롯들은 비활성화 한다.
  • ✅ 여기는 오브젝트 풀을 관리하는 PoolManager를 만들었기 때문에 이걸 사용해 리팩토링할 예정이다.
    내가 만든건데 정작 나만 아직 적용 못한 기이한 현상



인벤토리에 탭이 3개인데다 보여줘야 하는 데이터 정보가 너무나도 많아서 전체 인벤토리 코드는 매우 길고 지저분하다,,

한 번 했지만 인벤토리 리팩토링은 좀 더 고민해봐야 할 것 같다 ;ㅁ;

추가로 현재 인벤토리 쪽은 View와 Controller가 상호 참조를 하고 있어서 매우매우매우 마음에 들지 않는 구조이다.

추가 기능을 구현하면서 상점 UI쪽은 View는 Controller를 완전히 모르도록 구현하는데 성공했는데, 인벤토리 쪽에도 적용해봐야겠다!!

아무튼 짜잔 이런 탭 UI를 가진 인벤토리를 만들어봤다!!!

아이콘은 제작 중이라 빈 칸으로 나와서 허접같지만
우리 애 허접 아니에요
만든 사람은 허접이긴 한데



끗~~

0개의 댓글