유니티/인벤토리

[Unity] 인벤토리 - 2. UI와 아이템 버리기

이름?없음 2024. 2. 8. 21:41
반응형

이전 글에서는 기본적인 인벤토리 로직을 구현하였다

이번 글에서는 인벤토리의 UI와 아이템을 버리는 기능을 구현해 보도록 하겠다

반응형

일단 UI구현을 위해 저번에 짰던 인벤토리 로직에 이벤트를 추가해 주었다

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    
    private Dictionary<ItemDataSO, int> itemContainer = new();
    public static Inventory Instance { get; private set; }

    //아이템이 바뀌었을때의 이벤트
    public event Action<ItemDataSO, int> OnItemChanged;
    //새로운 아이템이 추가되었을때 이벤트
    public event Action<ItemDataSO> OnNewItemAdded;

    private void Awake()
    {
        
        Instance = this;

    }

    public void AddItem(Item item)
    {

        if (itemContainer.ContainsKey(item.itemData))
        {

            if(item.itemData.MaxStackCount > itemContainer[item.itemData])
            {

                itemContainer[item.itemData]++;

                //이벤트 실행
                OnItemChanged?.Invoke(item.itemData, itemContainer[item.itemData]);

                Destroy(item.gameObject);

            }

        }
        else
        {

            itemContainer.Add(item.itemData, 1);

            //이벤트 실행
            OnNewItemAdded?.Invoke(item.itemData);

            Destroy(item.gameObject);

        }

    }

    public void RemoveItem(ItemDataSO item, Vector2 pos)
    {
        
        if(itemContainer.ContainsKey(item))
        {

            Instantiate(item.ItemPrefab, pos, Quaternion.identity);

            itemContainer[item]--;

            //이벤트 실행
            OnItemChanged?.Invoke(item, itemContainer[item]);

            if (itemContainer[item] <= 0)
            {

                itemContainer.Remove(item);

            }


        }

    }

    private void OnDestroy()
    {
        
        Instance = null;

    }

}

 

그 후 Slot 스크립트를 구현해 주었다

using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;


public class Slot : MonoBehaviour, IPointerDownHandler
{

    private TMP_Text itemCountText;
    private Image itemImage;
    private ItemDataSO currentSaveItem;

    private void Awake()
    {
        
        itemCountText = GetComponentInChildren<TMP_Text>();
        itemImage = transform.Find("ItemImage").GetComponent<Image>();

    }

    public void Init(ItemDataSO item)
    {

        currentSaveItem = item;
        itemCountText.text = "1";
        itemImage.sprite = item.ItemSprite;
        
        //이벤트 구독
        Inventory.Instance.OnItemChanged += HandleItemAdded;

    }

    private void HandleItemAdded(ItemDataSO item, int count)
    {

        if(currentSaveItem == item)
        {

            //카운트가 0이라면?
            if(count == 0)
            {

                //슬롯 없에기
                Destroy(gameObject);

            }
            //아니라면?
            else
            {

                //텍스트 갱신
                itemCountText.text = count.ToString();

            }


        }

    }

    private void OnDestroy()
    {
        
        if(Inventory.Instance != null)
        {

            //이벤트 구독 해제
            Inventory.Instance.OnItemChanged -= HandleItemAdded;

        }


    }

    //이 오브젝트위에서 마우스를 눌렀다면?
    //IPointerDownHandler에 정의되어있음
    public void OnPointerDown(PointerEventData eventData)
    {

        //좌클릭이라면?
        if(eventData.button == PointerEventData.InputButton.Left)
        {

            //랜덤한좌표에 아이템 버리기
            Inventory.Instance.RemoveItem(currentSaveItem, UnityEngine.Random.insideUnitCircle);

        }

    }

}

나는 아이템이 버려지는 좌표를 랜덤 하게 설정해 주었다

 

그다음으로 인벤토리 UI를 관리할 InventoryViewer스크립트를 작성해 주었다

using UnityEngine;

public class InventoryViewer : MonoBehaviour
{

    [SerializeField] private Slot slotPrefab;
    [SerializeField] private Transform slotParent;

    private void Start()
    {

        //이벤트 구독
        Inventory.Instance.OnNewItemAdded += HandleItemAdded;

    }

    private void HandleItemAdded(ItemDataSO obj)
    {

        Instantiate(slotPrefab, slotParent).Init(obj);

    }
}

 

이제 UI를 구성해 줄 차례이다

일단 인벤토리의 백그라운드는 이런 식으로 구현하였다

SlotUI는 이런 식으로 만든 뒤 프리팹화 시켜주었다

컴포넌트

Slot

ItemImage

ItemText

이제 InventoryViewer스크립트를 아무 오브젝트에나 붙여주고 이런 식으로 할당해 준다

Slot은 아까 만든 슬롯프리팹이고

Panel은 아까만든 뒷배경이다

 

이후 실행해 보면?

인벤토리에 추가되는 것과 버리는 것이 아주 잘 작동하는 것을 확인할 수 있다
이 다음글에서는 인벤토리 드래그&드롭을 구현해 보겠다

반응형

'유니티 > 인벤토리' 카테고리의 다른 글

[Unity] 인벤토리 - 3. 드래그 드롭  (0) 2024.02.08
[Unity] 인벤토리 - 1. 기본 구현  (0) 2024.02.08