← Назад к вопросам

Как реализовать систему инвентаря в Unity?

1.0 Junior🔥 122 комментариев
#Unity Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Проектирование системы инвентаря в Unity

Реализация системы инвентаря — комплексная задача, требующая проработки архитектуры данных, UI и логики взаимодействия. Я поделюсь проверенным подходом, основанным на компонентно-ориентированном дизайне.

1. Базовая архитектура данных

Первым делом создаём структуры для хранения данных предметов и слота инвентаря. Использую ScriptableObject для настраиваемых параметров предметов.

// Базовый класс предмета как ScriptableObject
[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/Item")]
public class Item : ScriptableObject
{
    public string itemName = "New Item";
    public Sprite icon = null;
    public int maxStack = 1;
    public GameObject physicalPrefab;
    
    [TextArea(5, 10)]
    public string description;
    
    public virtual void Use()
    {
        // Базовая логика использования предмета
        Debug.Log($"Using {itemName}");
    }
}

2. Класс инвентаря и управления слотами

Реализую InventoryManager как синглтон для глобального доступа и InventorySlot для представления каждого слота.

// Класс для управления инвентарём
public class InventoryManager : MonoBehaviour
{
    public static InventoryManager Instance;
    
    public List<InventorySlot> slots = new List<InventorySlot>();
    public int capacity = 20;
    
    public UnityEvent<Item, int> onItemChanged;
    
    private void Awake()
    {
        if (Instance == null)
            Instance = this;
        else
            Destroy(gameObject);
            
        InitializeSlots();
    }
    
    void InitializeSlots()
    {
        for (int i = 0; i < capacity; i++)
        {
            slots.Add(new InventorySlot());
        }
    }
    
    public bool AddItem(Item item, int amount = 1)
    {
        // Поиск стекающегося предмета или пустого слота
        foreach (var slot in slots)
        {
            if (slot.item == item && slot.amount < item.maxStack)
            {
                slot.amount += amount;
                onItemChanged?.Invoke(item, slot.amount);
                return true;
            }
        }
        
        foreach (var slot in slots)
        {
            if (slot.item == null)
            {
                slot.item = item;
                slot.amount = amount;
                onItemChanged?.Invoke(item, amount);
                return true;
            }
        }
        
        Debug.LogWarning("Inventory is full!");
        return false;
    }
}

3. Система слота инвентаря

// Класс, представляющий один слот инвентаря
[System.Serializable]
public class InventorySlot
{
    public Item item;
    public int amount;
    
    public bool IsEmpty => item == null;
    
    public void Clear()
    {
        item = null;
        amount = 0;
    }
}

4. UI компоненты инвентаря

Для UI использую Grid Layout Group и префабы слотов. Ключевые компоненты:

  • InventoryUI — контроллер всего интерфейса инвентаря
  • InventorySlotUI — UI представление одного слота
  • ItemTooltip — всплывающая подсказка с описанием
// Контроллер UI слота
public class InventorySlotUI : MonoBehaviour, IPointerClickHandler
{
    public Image icon;
    public Text amountText;
    private InventorySlot slot;
    
    public void Setup(InventorySlot slot)
    {
        this.slot = slot;
        UpdateUI();
    }
    
    void UpdateUI()
    {
        if (slot.IsEmpty)
        {
            icon.enabled = false;
            amountText.enabled = false;
        }
        else
        {
            icon.sprite = slot.item.icon;
            icon.enabled = true;
            
            amountText.text = slot.amount > 1 ? slot.amount.ToString() : "";
            amountText.enabled = slot.amount > 1;
        }
    }
    
    public void OnPointerClick(PointerEventData eventData)
    {
        if (eventData.button == PointerEventData.InputButton.Left)
        {
            // Логика использования предмета
            if (!slot.IsEmpty)
                slot.item.Use();
        }
        else if (eventData.button == PointerEventData.InputButton.Right)
        {
            // Логика выброса предмета
            Debug.Log($"Dropping {slot.item.itemName}");
        }
    }
}

5. Расширенные возможности

Для полноценной системы добавляю:

Систему быстрых слотов (Hotbar):

public class Hotbar : MonoBehaviour
{
    public InventorySlot[] quickSlots = new InventorySlot[8];
    private int selectedIndex = 0;
    
    void Update()
    {
        // Переключение быстрых слотов цифровыми клавишами
        for (int i = 0; i < quickSlots.Length; i++)
        {
            if (Input.GetKeyDown(KeyCode.Alpha1 + i))
            {
                SelectSlot(i);
            }
        }
    }
}

Сериализацию для сохранения: Использую JSONUtility или BinaryFormatter для сохранения состояния инвентаря между сессиями.

6. Оптимизация и best practices

  • Object Pooling для UI элементов слотов при больших инвентарях
  • Event-driven архитектура через UnityEvents для уменьшения связности
  • Lazy initialization для загрузки иконок предметов
  • Кэширование ссылок на компоненты в Awake() для производительности
  • Разделение логики на Inventory (данные) и InventoryUI (представление)

7. Гибкая настройка через Inspector

Использую кастомные редакторы для удобной настройки:

#if UNITY_EDITOR
[CustomEditor(typeof(InventoryManager))]
public class InventoryManagerEditor : Editor
{
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        
        if (GUILayout.Button("Test Add Random Item"))
        {
            // Тестовая функциональность для дебага
        }
    }
}
#endif

Ключевые принципы моей реализации:

  1. Разделение ответственности — данные, логика и UI изолированы
  2. Гибкость через ScriptableObject — легко добавлять новые типы предметов
  3. Производительность — минимизация поисков по спискам, кэширование
  4. Расширяемость — виртуальные методы для переопределения логики
  5. Тестируемость — компоненты можно тестировать изолированно

Эта архитектура проверена в нескольких проектах и масштабируется от простых инвентарей до сложных систем с категориями, фильтрами, крафтингом и торговлей. Главное — начинать с минимально рабочей версии и постепенно добавлять фичи, сохраняя код чистым и модульным.

Как реализовать систему инвентаря в Unity? | PrepBro