在原本的 Inventory 的基础上,我发现一个问题,每当我需要列出一个新的列表的时候,我都需要创建一个新的 list 和 dectionary 在 Inventory 的每个方法中重新注册一遍,这太麻烦了,违背了低耦合性的原则,所以我对 inventory 重新进行了整理。
我创建了 IInventoryCategory 接口来对 Inventory 中常用的方法进行了抽象管理
IInventoryCategory.cs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public interface IInventoryCategory
{
ItemType GetItemType();
void AddItem(ItemData item);
void RemoveItem(ItemData item);
void UpdateUI();
void UpdateSelectedItem(ItemData selectedItem);
}
|
然后创建一个 InventoryCategory 用以管理大的类别
InventoryCategory.cs1 2 3 4 5 6 7 8 9
| private List<InventoryItem> items = new List<InventoryItem>(); private Dictionary<ItemData, InventoryItem> itemDictionary = new Dictionary<ItemData, InventoryItem>(); private UI_ItemSlot[] uiSlots; public InventoryCategory(UI_ItemSlot[] slots) { uiSlots = slots; }
public ItemType GetItemType() => items.Count > 0 ? items[0].data.itemType : ItemType.None;
|
同时将一些方法进行重写
- AddItem
AddItem1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public virtual void AddItem(ItemData item) { if (!itemDictionary.TryGetValue(item, out InventoryItem existingItem)) { InventoryItem newItem = new InventoryItem(item); items.Add(newItem); itemDictionary[item] = newItem; } else { existingItem.AddStack(); } UpdateUI(); }
|
- RemoveItem
RemoveItem1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public virtual void RemoveItem(ItemData item) { if (itemDictionary.TryGetValue(item, out InventoryItem existingItem)) { if (existingItem.stackSize > 1) { existingItem.RemoveStack(); } else { items.Remove(existingItem); itemDictionary.Remove(item); } }
UpdateUI(); }
|
- UpdateUI
1 2 3 4 5 6 7 8 9 10 11 12 13
| public virtual void UpdateUI() { foreach (var slot in uiSlots) slot.CleanUpSlot();
for (int i = 0; i < items.Count && i < uiSlots.Length; i++) { uiSlots[i].UpdateSlot(items[i]); } }
|
- UpdateSelectedItem
UpdateSelectedItem1 2 3 4 5 6 7 8 9 10 11
| public void UpdateSelectedItem(ItemData selectedItem) { foreach (var item in items) { item.data.isSelect = item.data == selectedItem; } }
|
由于我需要单独列出 Equipment 下的小分类:Book 和 Weapon
所以我需要再创建一个类来对 Equipment 中的小分类进行单独的筛选以及其他操作
EquipmentCategory.cs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| using System; using System.Collections.Generic; using System.Linq; using UnityEngine;
public class EquipmentCategory : MonoBehaviour, IInventoryCategory { private Dictionary<EquipmentType, List<InventoryItem>> typeToItems;
private Dictionary<EquipmentType, UI_ItemSlot[]> typeToUISlots;
public EquipmentCategory(Dictionary<EquipmentType, UI_ItemSlot[]> slotsMapping) { typeToItems = new Dictionary<EquipmentType, List<InventoryItem>>(); typeToUISlots = slotsMapping;
foreach (var type in typeToUISlots.Keys) { typeToItems[type] = new List<InventoryItem>(); } }
public ItemType GetItemType() { return ItemType.Equipment; }
public void AddItem(ItemData item) { if (item is ItemData_Equipment equipment) { var type = equipment.equipmentType;
var items = typeToItems[type];
var existingItem = items.FirstOrDefault(i => i.data == item); if (existingItem != null) { existingItem.AddStack(); } else { var newItem = new InventoryItem(item); items.Add(newItem); }
UpdateEquipmentSlots(type); } }
public void RemoveItem(ItemData item) { if (item is ItemData_Equipment equipment) { var type = equipment.equipmentType;
var items = typeToItems[type];
var existingItem = items.FirstOrDefault(i => i.data == item); if (existingItem != null) { if (existingItem.stackSize > 1) { existingItem.RemoveStack(); } else { items.Remove(existingItem); }
UpdateEquipmentSlots(type); } } } }
|
然后在 Inventory 中统一注册管理这些 Category
Inventory.cs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| private void InitializeCategories() { equipment = new List<InventoryItem>(); equipmentDictionary = new Dictionary<ItemData_Equipment, InventoryItem>();
inventoryItemSlot = inventorySlotParent.GetComponentsInChildren<UI_ItemSlot>(); stashItemSlot = stashSlotParent.GetComponentsInChildren<UI_ItemSlot>(); equipmentSlot = equpmentSlotParent.GetComponentsInChildren<UI_EquipmentSlot>(); bookSlot = bookSlotParent.GetComponentsInChildren<UI_ItemSlot>(); weaponSlot = weaponSlotParent.GetComponentsInChildren<UI_WeaponSlot>();
equipmentSlotsMapping = new Dictionary<EquipmentType, UI_ItemSlot[]> { { EquipmentType.Book, bookSlot }, { EquipmentType.Weapon, weaponSlot }, };
var equipmentCategory = new EquipmentCategory(equipmentSlotsMapping); categories = new Dictionary<ItemType, IInventoryCategory> { { ItemType.Equipment, equipmentCategory }, { ItemType.Material, new InventoryCategory(stashItemSlot) } };
}
|
随后就可以逐一优化方法,有新的列表加入的时候就不再需要全部注册一遍方法了
以 AddItem 为例
AddItem1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public void AddItem(ItemData _item) { if (_item == null) { Debug.LogWarning("Cannot add a null item to inventory."); return; } if (categories.TryGetValue(_item.itemType, out IInventoryCategory category)) { if (_item is ItemData_Equipment equipment) { var equipmentCategory = category as EquipmentCategory; equipmentCategory?.AddItem(equipment); } else { category.AddItem(_item); } } else { Debug.LogWarning($"No category found for ItemType {_item.itemType}. Check your category setup."); } }
|