아이템은 데이터 형식으로 관리하는게 좋다. 그러니까 인벤토리에서 사용할 아이템을 만들기 위해서 먼저 아이템을 관리하는 아이템매니저가 필요하다는 결론이 도출되었음
일단 아이템 목록을 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]);
}
}
}
마구마구 섞어놔도 잘 소팅되었다.