Redirect to the Docs main page.Docs

Items Metadata

Understanding Inventory Metadata

Learn how to use the InventoryMetadata system to add dynamic properties and behaviors to your inventory items.

What is InventoryMetadata?

InventoryMetadata is a powerful system in Ultimate Grid Inventory (UGI) that allows you to add dynamic properties and behaviors to your inventory items. Unlike static properties defined in ItemDataSo scriptable objects, metadata provides runtime-specific data that can change during gameplay.

Key Benefits of Using Metadata

  • Dynamic Properties: Add properties that can change during gameplay (stack counts, durability, etc.)
  • Runtime Behaviors: Implement item-specific behaviors like stacking, container functionality, or custom mechanics
  • Data Persistence: Metadata is automatically serialized when saving inventory state
  • Extensibility: Create custom metadata types for your specific game requirements

Built-in Metadata Types

Ultimate Grid Inventory includes several built-in metadata types:

InventoryMetadata (Base Class)

The base class that all metadata types inherit from. It provides:

  • A reference to the associated ItemTable
  • Initialization and lifecycle methods (Init, Awake, EvictLoad)
// Basic structure of the base InventoryMetadata class
public class InventoryMetadata
{
    [NonSerialized] public ItemTable ItemTable;
 
    public void Init(ItemTable item)
    {
        ItemTable = item;
        Awake();
    }
 
    public virtual void Awake() { }
 
    public virtual void EvictLoad() { }
}

CountableMetadata

Adds stacking functionality to items, allowing them to be combined and split:

  • Stack Count: Tracks how many items are in the stack
  • Max Stack: Defines the maximum stack size
  • Min Stack: Sets the minimum stack size (for splitting)
  • Combine: Methods to combine stacks of the same item
  • Split: Methods to split stacks into separate items

ContainerMetadata

Enables items to contain other items (like backpacks, chests, etc.):

  • Inventories: List of GridTable objects representing the container's internal storage
  • Open/Close: Methods to display and hide the container's inventory UI
  • Item Management: Methods to add, remove, and check for items in the container

How Metadata is Created and Assigned

The StaticMetadataCreator class automatically creates and assigns the appropriate metadata type based on the item's data type:

// How metadata is created based on item type
private static InventoryMetadata CreateInstancedMetadata(ItemDataSo itemDataSo)
{
    return itemDataSo switch
    {
        ItemContainerDataSo => new ContainerMetadata(),
        ItemStackableDataSo => new CountableMetadata(),
        _ => new InventoryMetadata()
    };
}

This happens automatically when an item is created, ensuring that each item has the appropriate metadata for its type.

Using Metadata in Your Scripts

Accessing Metadata

You can access an item's metadata through its InventoryMetadata property or using the generic GetMetadata<T>() method:

// Direct access to the metadata property
var metadata = itemTable.InventoryMetadata;
 
// Using the generic GetMetadata method (recommended)
var countableMetadata = itemTable.GetMetadata<CountableMetadata>();

Working with CountableMetadata

// Example: Checking if an item can be stacked and combining stacks
public bool TryCombineItems(ItemTable targetItem, ItemTable sourceItem)
{
    var targetMetadata = targetItem.GetMetadata<CountableMetadata>();
 
    if (targetMetadata == null)
        return false; // Not a stackable item
 
    return targetMetadata.Combine(sourceItem);
}
 
// Example: Splitting a stack in half
public void SplitItemStack(ItemTable stackableItem)
{
    var metadata = stackableItem.GetMetadata<CountableMetadata>();
 
    if (metadata != null)
        metadata.SplitHalf();
}

Working with ContainerMetadata

// Example: Getting all items from a container
public List<ItemTable> GetItemsFromContainer(ItemTable containerItem)
{
    if (containerItem.InventoryMetadata is not ContainerMetadata metadata)
        return new List<ItemTable>();
 
    return metadata.GetAllItems(false); // Pass false to get only direct items, or true for recursive retrieval
}
 
// Example: Adding an item to a container
public bool AddItemToContainer(ItemTable containerItem, ItemTable itemToAdd)
{
    var metadata = containerItem.GetMetadata<ContainerMetadata>();
 
    if (metadata == null)
        return false;
 
    var result = metadata.PlaceItemInInventory(itemToAdd);
    return result == GridResponse.Inserted;
}

Creating Custom Metadata Types

You can extend the InventoryMetadata system by creating your own custom metadata types:

  1. Create a new class that inherits from InventoryMetadata
  2. Override the Awake and EvictLoad methods as needed
  3. Add your custom properties and methods
  4. Update the StaticMetadataCreator to create your metadata type for specific items

Example: Creating a DurabilityMetadata

[Serializable]
public class DurabilityMetadata : InventoryMetadata
{
    [SerializeField] private float currentDurability;
    [SerializeField] private float maxDurability;
 
    public float CurrentDurability => currentDurability;
    public float MaxDurability => maxDurability;
 
    public override void Awake()
    {
        base.Awake();
 
        // Initialize from item data
        var durableItemData = ItemTable.GetItemData<DurableItemDataSo>();
        if (durableItemData != null)
        {
            maxDurability = durableItemData.MaxDurability;
            currentDurability = maxDurability; // Start at full durability
        }
    }
 
    public bool UseDurability(float amount)
    {
        currentDurability -= amount;
 
        if (currentDurability <= 0)
        {
            // Item has broken
            currentDurability = 0;
            return false;
        }
 
        // Update the item's visual representation if needed
        ItemTable.UpdateUI();
        return true;
    }
 
    public void Repair(float amount)
    {
        currentDurability = Mathf.Min(currentDurability + amount, maxDurability);
        ItemTable.UpdateUI();
    }
}

Then update the StaticMetadataCreator:

private static InventoryMetadata CreateInstancedMetadata(ItemDataSo itemDataSo)
{
    return itemDataSo switch
    {
        ItemContainerDataSo => new ContainerMetadata(),
        ItemStackableDataSo => new CountableMetadata(),
        DurableItemDataSo => new DurabilityMetadata(),
        _ => new InventoryMetadata()
    };
}

Best Practices

  1. Use GetMetadata<T>(): Always use the generic method to access metadata to ensure type safety
  2. Check for Null: Always check if the metadata exists before using it
  3. Keep Metadata Focused: Each metadata type should handle a specific aspect of item behavior
  4. Override Lifecycle Methods: Use Awake() to initialize and EvictLoad() to handle version changes
  5. Update UI: Call ItemTable.UpdateUI() when changing properties that affect the item's appearance

Next Steps

Now that you understand how to use InventoryMetadata, you can:

By leveraging the InventoryMetadata system, you can create rich, dynamic inventory items that enhance your game's depth and player experience.

On this page