Attributes give Item Categories, Item Definitions, and runtime Items named values such as Icon, Description, Attack, Durability, or BuyPrice. Declare each attribute on an Item Category, then place its value at the level that matches what the value describes and how often it can change.

Choose where the value belongs

Attribute collection Use it when Standard example
Item Category The value describes the category itself and can be inherited by child categories. CategoryIcon for Weapon
Item Definition Every Item created from one definition should share the value. Icon, Description, Attack, or BuyPrice on Iron Sword
Item Each runtime instance may need its own value. Durability on one Iron Sword or Fire Wand

Attributes can only be declared from the Item Category editor. Think of the category declaration as defining which named values are available. Item Definitions and Items then inherit, override, or modify the values declared for their category.

The Default Item on an Item Definition supplies the starting Item-level values for Items created from that definition. For example, Iron Sword and Fire Wand can share the Durability declaration from Weapon but start with different default values.

Follow the starter workflow

The standard documentation sample uses All > Consumable and All > Equippable > Weapon, with Health Potion, Iron Sword, and Fire Wand definitions.

  1. In the Item Categories editor, select All and declare Icon, Description, and BuyPrice in the Item Definition attribute collection.
  2. Select Weapon and declare Attack in the Item Definition collection.
  3. On Weapon, declare Durability in the Item collection. Make Weapon mutable and unique when every weapon instance must retain its own changing Durability.
  4. In the Item Definitions editor, set the shared display and price values for Health Potion, Iron Sword, and Fire Wand.
  5. Set Attack for Iron Sword and Fire Wand. Health Potion does not receive that field because Consumable does not inherit from Weapon.
  6. Set the starting Durability on the Default Item for Iron Sword and Fire Wand.
  7. Keep a value set to Inherit when its parent is correct; use Override for a value specific to the selected Category, Definition, or Item.

Do not redeclare the same attribute on every child category. Put a declaration on the closest common ancestor whose descendants all need it, then add narrower declarations only for values specific to one branch.

For the full editor sequence, including mutability and stacking decisions, follow Defining Attributes.

Understand inheritance and variants

An inherited value is resolved through the data model:

Selected attribute Where its parent value comes from
Item The Item Definition’s Default Item
Default Item A parent Item Definition’s Default Item, or the Item Category’s Item attribute
Item Definition A parent Item Definition, or the Item Category’s Item Definition attribute
Item Category The first parent category containing the attribute, or the type’s default value

Each value has one of three Variant choices:

  • Inherit gets the value from the parent shown by the editor.
  • Override stores a value directly on the selected object.
  • Modify evaluates an expression based on the inherited value, override value, or other attributes.

Use Override for the direct Attack value of Iron Sword. Use Inherit when a child definition should keep its parent’s value. Use Modify for a predictable relationship, such as an upgraded sword whose Attack is based on its parent definition.

Choose a supported name and type

Attribute values can use common types such as int, float, bool, string, Vector3, Unity objects, Item Amounts, Currency Amounts, Item Shapes, and Item Action Sets.

Use Common Attributes and Types when a built-in view or system expects a conventional name or value type. This is the only direct child page in this section and includes Description, Icon, BuyPrice, PickupPrefab, EquipmentPrefab, Shape, and other established attributes.

When the required value type is not listed, open Tools > Opsive > Unit Options and add it to the available types.

The Unit Options window listing an attribute value type that can be made available in the attribute type dropdown.

A custom class that inherits Attribute<T> can change expression parsing for that type. After creating the class, add it through Unit Options so it can be selected from the attribute type dropdown.

Editor checkpoints

Before entering Play Mode, confirm that:

  • The attribute is declared once in the intended collection on the appropriate Item Category.
  • Child categories and definitions show the expected inherited source.
  • Health Potion exposes the common display and price fields without Weapon-only fields.
  • Iron Sword and Fire Wand expose definition-level Attack and Default Item Durability.
  • The selected Variant is intentional: inherited values show their parent source, while overrides contain the expected local value.
  • Weapon is mutable and unique if two weapon Items must keep different Durability values.

Verify at runtime

  1. Add two Iron Sword Items, one Fire Wand Item, and a stack of Health Potion Items to the player’s Bag collection.
  2. Enter Play Mode and confirm that Item Views read each definition’s Icon and Description.
  3. Confirm that Iron Sword and Fire Wand report their own definition-level Attack values.
  4. Change the Durability of one Iron Sword and confirm that the other weapon Items keep their own values.
  5. Confirm that matching Health Potion Items can stack when the collection permits stacking.
  6. If a shop is configured, confirm that it reads each definition’s expected BuyPrice.

Runtime Item attribute values can be changed only when the Item is mutable. The Item’s direct category controls that choice.

Use Modify expressions

The built-in Modify expression evaluator supports int, float, and string attributes. It recognizes:

  • [OtherAttribute] to get another attribute by name.
  • <Override> to use this attribute’s override value.
  • <Inherited> to use this attribute’s inherited value.
  • $ before a value expression, such as $[OtherAttribute] or $<Inherited>, to resolve it from the perspective of the attribute that holds the expression.

Without $, referenced values are resolved from the perspective of the attribute that originally requested the result. This matters when one attribute inherits a Modify expression from another object.

Use Pre-evaluate when the result can be cached rather than recalculated every time it is requested. For a type that needs different parsing rules, create a custom Attribute type and its own parser.

When a value depends heavily on external state, a Modify expression may not be the clearest choice. A utility or extension method, a dedicated calculation class, or a Scriptable Object with a calculation function can keep that logic explicit while still accepting the Item as input.

Bind attributes to Item Objects

Add an Item Binding beside the Item Object when an attribute should drive a component property on an Item’s GameObject. A binding can connect a value such as damage to a component field. For more control, listen for the Item binding event and use attributes to choose a model, sprite, audio clip, or another Item-specific result.

Developer API

Attributes are accessed in a similar way on Item Categories, Item Definitions, and Items. These examples read values from an Item:

// Get the Attack attribute and its resolved, override, and inherited values.
var attackAttribute = item.GetAttribute<Attribute<int>>("Attack");
if (attackAttribute != null) {
    var attack = attackAttribute.GetValue();
    var attackOverride = attackAttribute.OverrideValue;
    var attackInherited = attackAttribute.GetInheritedValue();
}

// Read an Icon value directly.
if (item.TryGetAttributeValue("Icon", out Sprite icon)) {
    // Use the icon.
}

// Iterate through the Item's available attributes.
var includeItemDefinitionAttributes = true;
var includeItemCategoryAttributes = true;
var attributeCount = item.GetAttributeCount(
    includeItemDefinitionAttributes,
    includeItemCategoryAttributes);

for (int i = 0; i < attributeCount; i++) {
    var attribute = item.GetAttributeAt(
        i,
        includeItemDefinitionAttributes,
        includeItemCategoryAttributes);
    Debug.Log(attribute.GetValueAsObject());
}

Attribute declarations cannot be added directly to a runtime Item. A mutable Item can change values declared in its Item attribute collection. GetAttribute includes Definition and Category attributes by default and returns those shared objects, so changing a definition-level Attack affects every Item using that definition. For per-instance mutation, use the Item-level Durability declaration and disable the broader lookup:

if (!item.IsMutable) {
    // Immutable Items cannot change their attribute values at runtime.
    return;
}

var durabilityAttribute = item.GetAttribute<Attribute<int>>("Durability", false, false);
if (durabilityAttribute != null) {
    durabilityAttribute.SetOverrideValue(10);
    // Alternatively, derive Durability from its inherited starting value.
    durabilityAttribute.SetModifyExpression("<Inherited> - 5", true);
}

Be careful when an attribute contains a mutable reference type. Declare Slots as a mutable Item-level attribute for this example. Copy an inherited value before changing it, then store the copy as the override:

if (!item.IsMutable) { return; }
var itemSlotsAttribute = item.GetAttribute<Attribute<ItemAmounts>>("Slots", false, false);
if (itemSlotsAttribute != null) {
    var itemSlots = itemSlotsAttribute.GetValue();
    if (itemSlots == itemSlotsAttribute.OverrideValue) {
        itemSlots.Add(newItem);
    } else {
        itemSlots = new ItemAmounts(itemSlots);
        itemSlots.Add(newItem);
        itemSlotsAttribute.SetOverrideValue(itemSlots);
    }
}

Troubleshooting

  • A Definition or Item field is missing: Check that the attribute was declared in the correct collection on its Item Category or an inherited parent category.
  • A child shows the wrong value: Check the inherited source in the Attribute editor, then decide whether the child should inherit or override it.
  • Changing one weapon changes every copy: Check that Durability is an Item attribute and that Weapon is mutable and unique. Restrict mutation lookups to Item attributes so they cannot return a shared Definition or Category attribute.
  • A runtime value cannot be changed: Check the direct Item Category’s Mutable setting.
  • A Modify expression resolves an unexpected value: Check whether the reference should use the requesting Item’s perspective or the $ perspective of the attribute holding the expression.
  • A custom type is missing from the dropdown: Add the type through Tools > Opsive > Unit Options after the class compiles.