Skip to content
Development
Skill

/inventory-system

Inventory, equipment, and crafting patterns — ScriptableObject item definitions, slot-based inventory, equipment system, crafting recipes, UI binding. Load when implementing item management.

From plugin
everything-claude-unity
2442 skills20 agents27 commands
Install
$ npx -y skills add XeldarAlz/everything-claude-unity --skill inventory-system --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/inventory-system

Context preview

The summary Claude sees to decide when to auto-load this skill.

Inventory, equipment, and crafting patterns — ScriptableObject item definitions, slot-based inventory, equipment system, crafting recipes, UI binding. Load when implementing item management.

SKILL.md

inventory-system.SKILL.md
name: inventory-system
description: "Inventory, equipment, and crafting patterns — ScriptableObject item definitions, slot-based inventory, equipment system, crafting recipes, UI binding. Load when implementing item management."
globs: ["**/Inventory*.cs", "**/Item*.cs", "**/Equipment*.cs", "**/Craft*.cs"]

Inventory, Equipment, and Crafting System

Patterns for building a complete item management pipeline: define items as ScriptableObjects, store them in a slot-based inventory, equip gear, craft new items, and bind everything to UI.

Item Definition (ScriptableObject)

Every item in the game is defined as a ScriptableObject asset. This keeps data out of code, lets designers create items in the editor, and makes save/load straightforward (reference by ID, not by full object).

using UnityEngine;

public enum ItemType
{
    Consumable,
    Equipment,
    Material,
    QuestItem,
    Currency
}

public enum EquipmentSlotType
{
    None,
    Head,
    Body,
    Weapon,
    Shield,
    Accessory
}

[CreateAssetMenu(fileName = "New Item", menuName = "Inventory/Item Definition")]
public class ItemDefinition : ScriptableObject
{
    [Header("Identity")]
    public string itemId;           // Unique ID for save/load: "sword_iron_01"
    public string displayName;
    [TextArea(2, 4)]
    public string description;
    public Sprite icon;

    [Header("Stacking")]
    public bool isStackable = true;
    public int maxStackSize = 99;

    [Header("Type")]
    public ItemType itemType;
    public EquipmentSlotType equipSlot = EquipmentSlotType.None;

    [Header("Stats (for equipment)")]
    public int attackBonus;
    public int defenseBonus;
    public int healthBonus;
    public int speedBonus;

    [Header("Usage (for consumables)")]
    public int healAmount;
    public int manaRestoreAmount;

    [Header("Economy")]
    public int buyPrice;
    public int sellPrice;
}

**Naming convention for itemId:** Use snake_case with category prefix. Examples: `sword_iron_01`, `potion_health_small`, `mat_wood_plank`. This makes save files human-readable and debugging easier.

Item Registry

Maintain a central registry so you can look up an `ItemDefinition` by its `itemId`. This is essential for save/load (you save the ID string, then reconstruct the reference on load).

using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "ItemRegistry", menuName = "Inventory/Item Registry")]
public class ItemRegistry : ScriptableObject
{
    [SerializeField] private List<ItemDefinition> allItems;

    private Dictionary<string, ItemDefinition> _lookup;

    public void Initialize()
    {
        _lookup = new Dictionary<string, ItemDefinition>();
        foreach (var item in allItems)
        {
            if (_lookup.ContainsKey(item.itemId))
            {
                Debug.LogWarning($"Duplicate item ID: {item.itemId}");
                continue;
            }
            _lookup[item.itemId] = item;
        }
    }

    public ItemDefinition GetById(string itemId)
    {
        if (_lookup == null) Initialize();
        _lookup.TryGetValue(itemId, out var item);
        return item;
    }
}

Load all items into the registry at startup or use `Resources.LoadAll<ItemDefinition>("Items/")` if you prefer automatic discovery over an explicit list.

---

Inventory Slot

Each slot holds a reference to an item definition and a stack count. Null item means the slot is empty.

using System;

[Serializable]
public class InventorySlot
{
    public ItemDefinition item;
    public int count;

    public bool IsEmpty => item == null || count <= 0;

    public InventorySlot()
    {
        item = null;
        count = 0;
    }

    public InventorySlot(ItemDefinition item, int count)
    {
        this.item = item;
        this.count = count;
    }

    public void Clear()
    {
        item = null;
        count = 0;
    }
}

---

Inventory Class

The core inventory: a fixed-size array of slots with add, remove, and query methods. Raises an event whenever contents change so UI can react.

using System;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class Inventory
{
    [SerializeField] private int maxSlots = 20;
    [SerializeField] private List<InventorySlot> slots;

    public int MaxSlots => maxSlots;
    public IReadOnlyList<InventorySlot> Slots => slots;

    /// <summary>
    /// Fired whenever the inventory contents change.
    /// The int parameter is the slot index that changed (-1 for bulk operations).
    /// </summary>
    public event Action<int> OnChanged;

    public Inventory(int maxSlots)
    {
        this.maxSlots = maxSlots;
        slots = new List<InventorySlot>(maxSlots);
        for (int i = 0; i < maxSlots; i++)
            slots.Add(new InventorySlot());
    }

    /// <summary>
    /// Add an item. Returns the number of items that could NOT be added (overflow).
    /// </summary>
    public int Add(ItemDefinition item, int amount = 1)
    {
        if (item == null || amount <= 0) return amount;

        int remaining = amount;

        // First pass: stack onto existing slots with the same item
        if (item.isStackable)
        {
            for (int i = 0; i < slots.Count && remaining > 0; i++)
            {
                if (slots[i].item == item && slots[i].count < item.maxStackSize)
                {
                    int spaceInSlot = item.maxStackSize - slots[i].count;
                    int toAdd = Mathf.Min(remaining, spaceInSlot);
                    slots[i].count += toAdd;
                    remaining -= toAdd;
                    OnChanged?.Invoke(i);
                }
            }
        }

        // Second pass: place into empty slots
        for (int i = 0; i < slots.Count && remaining > 0; i++)
        {
            if (slots[i].IsEmpty)
            {
                int toAdd = item.isStackable
                    ? Mathf.Min(remaining, it
Read more
Ships witheverything-claude-unity

The ultimate Claude Code toolkit for Unity game development. A production-ready, plug-and-play system that gives Claude Code deep Unity expertise — from writing performant C# to building scenes, profiling performance, and triggering iOS/Android builds — all

Get the whole plugin

Other skills on everything-claude-unity.