using System.Collections.Generic; using UnityEngine; namespace Inventory { [System.Serializable] public class InventoryItem { public ItemData data; public int stackSize; public InventoryItem(ItemData source, int amount) { data = source; stackSize = amount; } public void AddToStack(int amount) { stackSize += amount; } public void RemoveFromStack(int amount) { stackSize -= amount; } } public class InventorySystem : MonoBehaviour { [Header("背包配置")] [Tooltip("背包最大格子数")] public int maxSlots = 20; // 背包内容列表 public List inventory = new List(); // 当前选中的格子索引(由 InventoryUI 同步) public int selectedSlotIndex = 0; // 这是一个简单的单例模式,方便全局访问(但在大项目中建议用依赖注入) public static InventorySystem Instance { get; private set; } private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); } else { Instance = this; // 初始化固定大小的背包,填充 null InitializeInventory(); SanitizeInventory(); } } private void InitializeInventory() { inventory.Clear(); for (int i = 0; i < maxSlots; i++) { inventory.Add(null); } } private void SanitizeInventory() { if (inventory == null) inventory = new List(); if (inventory.Count > maxSlots) { inventory.RemoveRange(maxSlots, inventory.Count - maxSlots); } else { while (inventory.Count < maxSlots) { inventory.Add(null); } } for (int i = 0; i < inventory.Count; i++) { InventoryItem item = inventory[i]; if (item == null) continue; if (item.data == null || item.stackSize <= 0) { inventory[i] = null; } } } /// /// 添加物品到背包 /// /// 物品数据 /// 添加数量 /// 是否成功添加(哪怕只添加了一部分也算成功) public bool Add(ItemData referenceData, int amount) { if (referenceData == null) { Debug.LogError("[Inventory] 尝试添加空的 ItemData(referenceData 为 null)。"); return false; } if (amount <= 0) return false; SanitizeInventory(); // 剩余需要添加的数量 int remainingAmount = amount; // 1. 如果物品可堆叠,先尝试填满已有的堆叠 if (referenceData.isStackable) { // 遍历所有格子寻找同类物品 for (int i = 0; i < inventory.Count; i++) { InventoryItem item = inventory[i]; if (item != null && item.data == referenceData) { // 如果这个堆叠还没满 if (item.stackSize < referenceData.maxStackSize) { // 计算这个格子还能塞多少个 int spaceInStack = referenceData.maxStackSize - item.stackSize; // 实际能塞进去的数量 int amountToAdd = Mathf.Min(remainingAmount, spaceInStack); item.AddToStack(amountToAdd); remainingAmount -= amountToAdd; Debug.Log($"[Inventory] 堆叠更新: {referenceData.displayName}, 当前堆叠数: {item.stackSize}"); if (remainingAmount <= 0) return true; } } } } // 2. 如果还有剩余,寻找新格子 while (remainingAmount > 0) { int targetSlotIndex = -1; // 优先级 A: 检查当前选中的格子是否为空 if (selectedSlotIndex >= 0 && selectedSlotIndex < maxSlots && inventory[selectedSlotIndex] == null) { targetSlotIndex = selectedSlotIndex; } // 优先级 B: 如果选中格子不空,从头寻找第一个空位 else { for (int i = 0; i < maxSlots; i++) { if (inventory[i] == null) { targetSlotIndex = i; break; } } } // 如果没找到空位,说明背包满了 if (targetSlotIndex == -1) { Debug.LogWarning("[Inventory] 背包已满!无法添加更多物品。"); return remainingAmount < amount; } // 创建新物品项并填入目标格子 int addCount = referenceData.isStackable ? Mathf.Min(remainingAmount, referenceData.maxStackSize) : 1; InventoryItem newItem = new InventoryItem(referenceData, addCount); inventory[targetSlotIndex] = newItem; // 填入空位 remainingAmount -= addCount; Debug.Log($"[Inventory] 添加新物品到格子 {targetSlotIndex}: {referenceData.displayName}, 数量: {addCount}"); } return true; } public void Remove(ItemData referenceData, int amount) { if (referenceData == null) return; if (amount <= 0) return; SanitizeInventory(); int remaining = amount; for (int i = 0; i < inventory.Count; i++) { InventoryItem item = inventory[i]; if (item == null) continue; if (item.data != referenceData) continue; int take = Mathf.Min(remaining, item.stackSize); item.RemoveFromStack(take); remaining -= take; if (item.stackSize <= 0) { inventory[i] = null; } if (remaining <= 0) break; } } /// /// 从指定格子移除物品 /// public void RemoveFromSlot(int slotIndex, int amount) { SanitizeInventory(); if (slotIndex < 0 || slotIndex >= inventory.Count) return; InventoryItem item = inventory[slotIndex]; if (item != null) { item.RemoveFromStack(amount); if (item.stackSize <= 0) { inventory[slotIndex] = null; // 置空该格子 } } } } }