UI와 게임로직이 직접적으로 연결 될 수 밖에 없는 구조였다.
그래서 이를 수정하고자 MVP패턴을 활용하여 수정하기로 하였다.
하이어라키 제네릭 타입의 싱글톤을 상속받는 InventoryManager을 만들었다.
using UnityEngine;
public class InventoryManager : Singleton<InventoryManager>
{
public Inventory inventory { get; private set; }
[SerializeField] private Transform itemSlotParent;
private UI_ItemSlot[] inventorySlot;
private void Awake()
{
inventory = ScriptableObject.CreateInstance<Inventory>();
inventorySlot = itemSlotParent.GetComponentsInChildren<UI_ItemSlot>();
}
private void UpdateSlotUI()
{
for(int i = 0; i < inventorySlot.Length; i++)
{
inventorySlot[i].CleanUpSlot();
}
for (int i = 0; i < inventory.inventoryList.Count; i++)
{
inventorySlot[i].UpdateSlot(inventory.inventoryList[i]);
}
}
public void AddItem(ItemData _data)
{
if (_data.itemtype == ItemType.Equipment)
inventory.AddToInventory(_data);
UpdateSlotUI();
}
public void RemoveItem(ItemData _itemData)
{
if (inventory.inventoryDictionary.TryGetValue(_itemData, out InventoryItem item))
{
if (item.stack > 1)
{
item.RemoveStack();
}
else
{
inventory.inventoryList.Remove(item);
inventory.inventoryDictionary.Remove(_itemData);
}
}
}
}
로직부분을 싱글톤에서 관리하고 UI를 업데이트 하기 때문에 실제 Inventory와 Slot의 의존성을 낮출 수 있었다.
이제 인벤토리는 하이어라키가아닌 ScriptableObject로 관리된다.
public class Inventory : ScriptableObject
{
public List<InventoryItem> inventoryList = new List<InventoryItem>();
public Dictionary<ItemData, InventoryItem> inventoryDictionary = new Dictionary<ItemData, InventoryItem>();
public void AddToInventory(ItemData _itemData)
{
if(inventoryDictionary.TryGetValue(_itemData,out InventoryItem item))
{
item.AddStack();
}
else
{
InventoryItem newItem = new InventoryItem(_itemData);
inventoryList.Add(newItem);
inventoryDictionary.Add(_itemData,newItem);
}
}
}
public class UI_ItemSlot : MonoBehaviour
{
[SerializeField] private Image itemIcon;
[SerializeField] private TextMeshProUGUI itemStack;
public InventoryItem item;
public void UpdateSlot(InventoryItem _newItem)
{
item = _newItem;
itemIcon.color = Color.white;
if (item != null)
{
itemIcon.sprite = item.data.icon;
if (item.stack > 1)
{
itemStack.text = item.stack.ToString();
}
else itemStack.text = "";
}
}
public void CleanUpSlot()
{
item = null;
itemIcon.sprite = null;
itemIcon.color = Color.clear;
itemStack.text = "";
}
}
실제 우리가 볼 UI를 세팅하는 부분이다.
프로토타입의 모습이다.