Files
WhaleAdventure_VR/Assets/My project/Inventory/Scripts/InventoryManager.cs
skrwns304@gmail.com b1e85a5b89 2026-06-19 UI, UI로직
2026-06-19 14:27:40 +09:00

186 lines
4.7 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
[Serializable]
public class InventoryItemStack
{
public InventoryItemType itemType;
[Min(0)] public int count;
}
[Serializable]
public class InventoryItemChangedEvent : UnityEvent<InventoryItemType, int>
{
}
/// <summary>
/// 실제 아이템 개수를 관리하는 중심 스크립트입니다.
/// UI를 직접 수정하지 않고, 아이템 개수 변경 이벤트만 알려줍니다.
/// </summary>
[DisallowMultipleComponent]
public class InventoryManager : MonoBehaviour
{
[Header("Initial Items")]
[SerializeField] private List<InventoryItemStack> initialItems = new List<InventoryItemStack>();
[Header("Events")]
public InventoryItemChangedEvent onItemCountChanged;
public UnityEvent onInventoryChanged;
[Header("Debug")]
[SerializeField] private bool showDebugLog = true;
private readonly Dictionary<InventoryItemType, int> itemCounts = new Dictionary<InventoryItemType, int>();
public event Action<InventoryItemType, int> ItemCountChanged;
public event Action InventoryChanged;
private void Awake()
{
InitializeFromInspector();
}
private void Start()
{
NotifyAllItemsChanged();
}
private void InitializeFromInspector()
{
itemCounts.Clear();
foreach (InventoryItemType itemType in Enum.GetValues(typeof(InventoryItemType)))
itemCounts[itemType] = 0;
for (int i = 0; i < initialItems.Count; i++)
{
InventoryItemStack stack = initialItems[i];
if (stack == null)
continue;
itemCounts[stack.itemType] = Mathf.Max(0, stack.count);
}
}
public void AddItem(InventoryItemType itemType)
{
AddItem(itemType, 1);
}
public void AddItem(InventoryItemType itemType, int amount)
{
if (amount <= 0)
return;
int newCount = GetItemCount(itemType) + amount;
SetItemCount(itemType, newCount);
if (showDebugLog)
Debug.Log($"[InventoryManager] {itemType} +{amount} => {newCount}");
}
public bool RemoveItem(InventoryItemType itemType)
{
return RemoveItem(itemType, 1);
}
public bool RemoveItem(InventoryItemType itemType, int amount)
{
if (amount <= 0)
return false;
int current = GetItemCount(itemType);
if (current < amount)
{
if (showDebugLog)
Debug.LogWarning($"[InventoryManager] {itemType} 부족: 현재 {current}, 필요 {amount}");
return false;
}
SetItemCount(itemType, current - amount);
return true;
}
public void SetItemCount(InventoryItemType itemType, int count)
{
int clampedCount = Mathf.Max(0, count);
int previousCount = GetItemCount(itemType);
if (previousCount == clampedCount)
return;
itemCounts[itemType] = clampedCount;
NotifyItemChanged(itemType, clampedCount);
}
public int GetItemCount(InventoryItemType itemType)
{
if (itemCounts.TryGetValue(itemType, out int count))
return count;
return 0;
}
public bool HasItem(InventoryItemType itemType)
{
return GetItemCount(itemType) > 0;
}
public bool HasItem(InventoryItemType itemType, int requiredAmount)
{
return GetItemCount(itemType) >= Mathf.Max(1, requiredAmount);
}
public void ClearInventory()
{
foreach (InventoryItemType itemType in Enum.GetValues(typeof(InventoryItemType)))
itemCounts[itemType] = 0;
NotifyAllItemsChanged();
}
public IReadOnlyDictionary<InventoryItemType, int> GetAllItemCounts()
{
return itemCounts;
}
private void NotifyItemChanged(InventoryItemType itemType, int count)
{
ItemCountChanged?.Invoke(itemType, count);
InventoryChanged?.Invoke();
onItemCountChanged?.Invoke(itemType, count);
onInventoryChanged?.Invoke();
}
private void NotifyAllItemsChanged()
{
foreach (KeyValuePair<InventoryItemType, int> pair in itemCounts)
{
ItemCountChanged?.Invoke(pair.Key, pair.Value);
onItemCountChanged?.Invoke(pair.Key, pair.Value);
}
InventoryChanged?.Invoke();
onInventoryChanged?.Invoke();
}
#if UNITY_EDITOR
private void OnValidate()
{
if (initialItems == null)
return;
for (int i = 0; i < initialItems.Count; i++)
{
if (initialItems[i] != null)
initialItems[i].count = Mathf.Max(0, initialItems[i].count);
}
}
#endif
}