인벤토리 만들기 2

Tom·6일 전
0

아이템은 데이터 형식으로 관리하는게 좋다. 그러니까 인벤토리에서 사용할 아이템을 만들기 위해서 먼저 아이템을 관리하는 아이템매니저가 필요하다는 결론이 도출되었음

아이템 관리하기

일단 아이템 목록을 csv파일로 만들고 파싱하면 되는데...일단 귀찮으니까 스크립트로 해결했음

using System.Collections.Generic;
using UnityEngine;
public class Item
{
    public int id;
    public string name;
    public string description;
    public Item(int _id, string _name, string _description)
    {
        id = _id;
        name = _name;
        description = _description;
    }
}

public class ItemManager : Singleton<ItemManager>
{
    public Dictionary<int, Item> itemDictionary = new Dictionary<int, Item>();

    protected override void Init()
    {
        base.Init();

        itemDictionary.Add(1, new Item(1, "HalfMask", "반쪽짜리 마스크"));
        itemDictionary.Add(2, new Item(2, "LessScaryMask", "덜 무서운 마스크"));
        itemDictionary.Add(3, new Item(3, "RedMask", "빨간 마스크"));
        itemDictionary.Add(4, new Item(4, "ScaryMask", "무서운 마스크"));
        itemDictionary.Add(5, new Item(5, "SuperScaryMask", "엄청 무서운 마스크"));
        itemDictionary.Add(6, new Item(6, "TwoHornMask", "뿔이 달린 마스크"));
        itemDictionary.Add(7, new Item(7, "WhiteMask", "하얀 마스크"));
    }

    public Item GetItemById(int id)
    {
        itemDictionary.TryGetValue(id, out var item);
        return item;
    }
}

일단 ID를 통해 아이템을 불러올 수 있는 기능만 만들어놨다. 이제 이 아이템을 인벤토리에 추가해줄 수 있는 기능이 필요함. 아이템을 획득하면 비어있는 가장 처음 칸에 아이템을 더해줘야 한다.

using System.Collections.Generic;
using UnityEngine;

public class Inventory : MonoBehaviour
{
    public List<Item> itemList = new List<Item>();
    public InventorySlot[] inventory;

    private GameObject inventoryItemPrefab;
    private void Awake()
    {
        inventoryItemPrefab = Resources.Load<GameObject>("Test/InventoryItem");
        int childCount = transform.childCount;
        inventory = new InventorySlot[childCount];

        for(int i = 0; i < childCount; i++)
        {
            inventory[i] = transform.GetChild(i).GetComponent<InventorySlot>();
        }
    }

    public void AddItemToInventoryById(int itemId)
    {
        InventorySlot firstEmptySlot = FindFirstEmptySlot();

        if (firstEmptySlot == null)
        {
            Debug.Log("인벤토리가 꽉찻슴");
            return;
        }

        GameObject instantiatedItem = Instantiate(inventoryItemPrefab);
        InventoryItem newItem = instantiatedItem.GetComponent<InventoryItem>();
        if (newItem != null)
        {
            newItem.SetItem(ItemManager.Instance.GetItemById(itemId));
            instantiatedItem.transform.SetParent(firstEmptySlot.transform);
            instantiatedItem.transform.localPosition = Vector3.zero;
        }
    }


    private InventorySlot FindFirstEmptySlot()
    {
        for (int i = 0; i < inventory.Length; i++)
        {
            if (inventory[i].IsEmpty)
            {
                return inventory[i];
            }
        }
        return null;
    }
}

인벤토리 아이템을 프리펩으로 만들어서 Resource에 넣어둔 뒤 랜덤한 인덱스의 아이템을 불러와봤다.

using UnityEngine;
public class Test2 : MonoBehaviour
{
    public Inventory inventory;
    private void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            int rnd = Random.Range(1, 8);
            Item item = ItemManager.Instance.GetItemById(rnd);
            inventory.AddItemToInventory(item);
        }
    }
}

스페이스바를 눌러보면~
인벤토리에 정상적으로 아이템이 배치되는걸 볼 수 있었따

종류별로 정렬도 해보자

정렬은 저번에 해봤다. 굳이 또? 음 굳이 또 해. 아이템에 별로 정보가 없으니 간단하게 id순으로 정렬하는것만 만들어보자. 근데 어케해야됨?

인벤토리 하위에 바로 아이템이 존재하는것이 아닌 인벤토리에서 슬롯을 거쳐 아이템이 있기 때문에 아이템과 슬롯을 저장해놔야할 필요성을 느꼈음. 또 아이템ID가 중복되는 경우가 있어 아이템 획득 순서에 따라 인벤토리에서 사용하는 유니크한 키를 부여해서 소팅해보기로했다.

private Dictionary<int, InventoryItem> idItemPair = new Dictionary<int, InventoryItem>();
private int idCount = 0;
List<int> uniqIdList = new List<int>();

일단 인벤토리에 해시테이블과 키를 부여하기위한 idCount, 유니크키를 저장할 리스트를 만들어줬다. 그리고 아이템을 인벤토리에 더해주는 시점에 이 키를 생성해서 리스트에 넣어주고,

    public void AddItemToInventoryById(int itemId)
    {
			// ~대충 원래 있던 코드~
            
            int itemUniqId = itemId * 1000 + idCount++;

            if (!idItemPair.ContainsKey(itemUniqId))
            {
                idItemPair[itemUniqId] = newItem;
                uniqIdList.Add(itemUniqId);
            }
        }
    }

이 순서대로 소팅을 해봤슴.

    public void SortItem()
    {
        uniqIdList.Sort();

        for (int i = 0; i < uniqIdList.Count; i++)
        {
            int itemKey = uniqIdList[i];
            if (idItemPair.TryGetValue(itemKey, out InventoryItem item))
            {
                item.transform.SetParent(inventory[i].transform);
                item.transform.localPosition = Vector3.zero;
                item.SetSlot(inventory[i]);
            }
        }
    }

마구마구 섞어놔도 잘 소팅되었다.

profile
여기 글은 보통 틀린 경우가 많음
post-custom-banner

0개의 댓글