3 분 소요

Intro

이번 포스팅에서는 인벤토리에 아이템을 추가해보는 기능을 구현해봤습니다.

지난 포스팅에서 아이템 아이콘을 불러오는 방식을 아래와같이 구현했습니다.

image


이 방식을 이용하여 아이템을 생성하고, 인벤토리에 아이템 데이터를 추가하고, 추가된 아이템 아이콘을 인벤토리에 띄우는것까지 해보려고합니다.

image


대충 위와같은 방식으로 진행됩니다.


/* Inventory 클래스
Inventory 클래스에서 DataManager에 접근하여 데이터를 받아옵니다.

인벤토리에 아이템을 추가하기위해 AddItem 함수를 호출합니다.

AddItem 함수에서는 인벤토리내의 빈 슬롯을 찾아 그 슬롯의 인덱스번호의 아이템 배열에 객체를 생성합니다.

그런다음 슬롯 정보를 갱신하는 UpdateSlot 함수를 호출합니다.
*/

-------------------------------------------------------------

/* InventoryUI 클래스
Inventory 클래스의 UpdateSlot 함수는 InventoryUI 클래스의 SetItemIcon 함수를 호출합니다.

이때 생성한 아이템의 정보중 아이템 아이콘 이름을 매개변수로 넘겨줍니다.

InventoryUI 클래스는 슬롯들의 정보를 관리하고있으므로 넘겨받은 index와 아이콘 이름을 

개별 슬롯인 ItemSlotUI 클래스의 SetItemIcon 함수를 호출하여 넘겨줍니다.
*/

-------------------------------------------------------------

/* ItemSlotUI 클래스
마지막으로 ItemSlotUI 클래스에서는 넘겨받은 아이콘 이름을 가지고 

ResourceManager에 접근하여 어드레서블 에셋에 등록한 Sprite를 찾아 세팅합니다.
*/

Inventory 클래스

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

public class Inventory : MonoBehaviour
{
    public ItemData[] ItemDataArray;

    public int Capacity { get; private set; }   // 인벤토리 수용한도

    [SerializeField] InventoryUI inventoryUI;
    [SerializeField] GameObject inventoryGo;
    [SerializeField] Item[] items;

    private bool inventoryKeydown;              // 인벤토리 키(I)
    private int initCapacity = 24;              // 초기 인벤토리 수용한도
    private int maxCapacity = 36;               // 최대 인벤토리 수용한도

  
    private void Awake()
    {
        // 인벤토리에서 관리할 수 있는 아이템은 최대 36개
        items = new Item[maxCapacity];                  
        ItemDataArray = new ItemData[maxCapacity];

        // 초기 수용량 : 24(임시)
        Capacity = initCapacity;

        inventoryUI.SetInventoryRef(this);
    }

    private void Start()
    {
        UpdateAccessibleSlots();
        InitTest();
    }

    private void Update()
    {
        inventoryKeydown = Input.GetButtonDown("Inventory");
        SetActiveUI();
    }

    // 인벤토리에 아이템 추가해보기(임시)
    private void InitTest()
    {
        // 기본 검 ID
        int testItem01 = 1001;

        // 기본 검 데이터 가져오기
        WeaponItemData weaponData = DataManager.Instance.GetDataById(testItem01);

        // 업 캐스팅(WeaponItemData => ItemData)
        ItemDataArray[0] = weaponData;

        // 다운 캐스팅
        if (ItemDataArray[0] is WeaponItemData)
            AddItem(ItemDataArray[0]);

    }

    // 인벤토리 UI 활성/비활성화
    private void SetActiveUI()
    {
        if(inventoryKeydown)
        {
            if (inventoryGo.activeSelf)
                inventoryGo.SetActive(false);
            else
                inventoryGo.SetActive(true);
        }

    }

    // 유효한 인덱스 번호인지 확인
    private bool IsValidIndex(int index)
    {
        return index >= 0 && index < Capacity;
    }

    // 인벤토리 앞쪽부터 비어있는 슬롯 인덱스 탐색(성공시 빈슬롯 인덱스 반환, 실패시 -1 반환)
    private int FindEmptySlotIndex(int startIndex = 0)
    {
        // 첫슬롯부터 전체 슬롯 탐색
        for(int i = startIndex; i < Capacity; i++)
        {
            // 빈 슬롯이 있다면 그 슬롯의 인덱스 반환
            if (items[i] == null)
                return i;
        }

        // 빈 슬롯이 없으면 -1 반환
        return -1;
    }

    // 인덱스 슬롯 갱신
    private void UpdateSlot(int index)
    {
        // 유효한 슬롯만
        if (!IsValidIndex(index)) return;

        Item item = items[index];

        // 슬롯에 아이템 존재
        if(item != null)
        {
            // 1. 아이콘 등록
            inventoryUI.SetItemIcon(index, item.Data.ItemIcon);
        }
    }

    // 해당 인덱스의 슬롯이 아이템을 갖고있는지 확인
    public bool HasItem(int index)
    {
        // 유효하고 슬롯에 아이템이 들어있으면 True
        return IsValidIndex(index) && items[index] != null;
    }

    // 활성화 시킬 슬롯범위 업데이트
    public void UpdateAccessibleSlots()
    {
        inventoryUI.SetAccessibleSlotRange(Capacity);
    }

    // 인벤토리에 아이템 추가(잉여 아이템 갯수 리턴, 리턴이 0이면 모두 성공)
    public int AddItem(ItemData itemData, int amount = 1)
    {
        int index;

        // 1. ItemData가 CountableItem일 경우 => 갯수가 2개~99개까지 가능(아직 미구현)
        
        // 2. 나머지
        // 수량이 하나일 경우
        if(amount == 1)
        {
            // 빈 슬롯을 찾아서 아이템 생성 후 슬롯에 추가
            index = FindEmptySlotIndex();

            // 빈 슬롯이 있다면
            if(index != -1)
            {
                items[index] = itemData.CreateItem();
                amount = 0;

                Debug.Log(items[index].Data.ItemIcon);
                // 슬롯 갱신
                UpdateSlot(index);
            }
        }

        return amount;
    }
}


추가된 부분만 설명해놓았습니다.

  • IsValidIndex : 그 인덱스번호의 슬롯이 유효한지 확인하는 함수입니다.
    • 결과로 참 또는 거짓을 반환합니다.
  • FindEmptySlotIndex : 인벤토리 앞쪽부터 검사하여 빈 슬롯의 인덱스를 찾는 함수입니다.
    • 성공했다면 찾은 빈 슬롯의 인덱스를, 실패했다면 -1를 반환합니다.
  • HasItem : 그 인덱스번호의 슬롯에 아이템이 존재하는지 확인하는 함수입니다.
  • AddItem : 아이템 객체를 생성하여 인벤토리에 추가합니다.
    • 추가할 때는 앞쪽 빈칸부터 채워집니다.
  • UpdateSlot : 아이템 아이콘을 등록합니다.
  • InitTest : 임시 테스트를 위하여 기본검 데이터를 추가했습니다.

InventoryUI 클래스

    // 아이콘 등록
    public void SetItemIcon(int index, string icon)
    {
        slotUIList[index].SetItemIcon(icon);
    }
  • SetItemIcon : 아이콘을 등록할 슬롯의 인덱스와, 등록할 아이콘 이름을 넘겨받아 ItemSlotUI 클래스의 SetItemIcon 함수를 호출합니다.
    • 특정 index 번호의 슬롯에 접근합니다.

ItemSlotUI 클래스

    // 슬롯에 아이템 아이콘 등록
    public void SetItemIcon(string itemSprite)
    {
        if(itemSprite != null)
        {
            // 아이콘 데이터 가져오기
            ResourceManager.Instance.LoadIcon(itemSprite, sprite =>
            {
                // 성공
                if (sprite != null)
                {
                    // 아이콘 설정
                    iconImage.sprite = sprite;
                    ShowIcon();
                }
                else
                {
                    Debug.Log($"Failed to load icon for item : {itemSprite}");
                }
            });
        }
        else
        {
            RemoveItem();
        }
    }

    // 슬롯에서 아이템 제거
    public void RemoveItem()
    {
        iconImage.sprite = null;
        HideIcon();
        HideText();
    }
  • SetItemIcon 함수에서는 넘겨받은 아이콘 이름을 통해 ResourceManager의 LoadIcon 함수를 호출하여 아이콘을 등록합니다.
    • 넘겨받은 아이콘 이름이 없다면 그 슬롯의 아이템 아이콘, 텍스트를 비활성화합니다.(아이템 제거)

테스트

image

댓글남기기