Item Asset Identifier SO Documentation

This document covers the Item (ItemDefinitionSO) ScriptableObject — what it is, how to create one, what every field does, all available parameters, and how the stacking system works.

For the step-by-step workflow guide (creating the effect script, making a new ItemEffect SO, etc.) see Creating a New Item Guide.


Table of Contents

  1. Overview
  2. Class Hierarchy
  3. Creating a New Item SO
  4. Assigning a GUID
  5. Registering in the Catalogue
  6. ItemDefinitionSO — Field Reference
  7. Stacking System In-Depth
  8. Proc Trigger Types
  9. Effect Conditions
  10. Enum Reference
  11. Pre-Build Catalogue Validation

1. Overview

ItemDefinitionSO is the data asset that defines a collectable item — its name, description, rarity, category, how it scales with stacks, and what it actually does. It does not hold runtime state. At runtime, ItemInstance wraps the definition and tracks the live stack count.

Items are held by units in a UnitInventory. When a relevant proc fires (e.g., a unit takes damage), the inventory iterates its items and executes any ItemEffectConfig whose triggerType matches, subject to proc chance and any effect conditions.

All items live under:

Assets/Assets/Asset Identifier SOs/Items/

Catalogue key: ITEMS_CATALOGUE


2. Class Hierarchy

ScriptableObject  (Unity)
└── AssetIdentifierBaseSO
        guid  (string, private, read-only in editor)
        GUID  (string property)
        GetGUID() → string
        GenerateNewGUID()  [ContextMenu]
    └── DefinitionSO  (abstract)
            displayName  (string)
        └── ItemDefinitionSO  (also implements IPurchasable)

Scripts:

  • AssetIdentifierBaseSOAssets/Scripts/Game Management/Asset Identifiers/AssetIdentifierBaseSO.cs
  • DefinitionSOAssets/Scripts/DeveloperConsole/ConsoleCommands/DefinitionSO.cs
  • ItemDefinitionSOAssets/Scripts/Item System/ItemDefinitionSO.cs

3. Creating a New Item SO

  1. In the Project window, navigate to Assets/Assets/Asset Identifier SOs/Items/.
  2. Right-click → Create → Items → Item Definition.
  3. Name the asset to match the item’s display name.

Tip

Keep file names and displayName values consistent. The Auto-Fill catalogue tool sorts assets by file name.


4. Assigning a GUID

Every item SO must have a unique GUID. This is the stable key the runtime uses to look up the item in the catalogue and to identify it in save data, proc attribution, and UI lookups.

To generate a GUID:

  1. Select the item SO in the Project window.
  2. In the Inspector, right-click the component header (or use the three-dot menu) and choose Generate New GUID.
  3. The guid field will populate with a UUID v4 string (e.g., ccfe8197-9aee-4ff5-b07c-44c8c5b63309).
  4. Save the asset.

Warning

Never edit the guid field by hand. It is marked read-only in the Inspector for this reason. Never copy-paste a GUID from another SO — duplicate GUIDs will cause AssetCatalogueSO.InitializeCatalogue() to silently skip one entry, producing silent runtime failures. The repository has a commit specifically addressing this: fixed merge conflicts, fixed duplicate guid.

If an item is missing a GUID, the catalogue will log:

Asset Identifier [name] is missing a valid asset or GUID

and the item will not be accessible in-game.


5. Registering in the Catalogue

After creating and assigning a GUID, add the item to the ITEMS_CATALOGUE:

  1. Navigate to Assets/Assets/Catalogues/ and open the Item Catalogue asset.
  2. In the Inspector, scroll to Auto-Fill Catalogue.
  3. Select Items from the dropdown.
  4. Click the green Fill with Items button.

This scans the project for all ItemDefinitionSO assets and replaces the catalogue list (sorted alphabetically). Run it whenever an item SO is added, removed, or renamed.

A pre-build check runs automatically before every build and will warn if the catalogue is out of sync. See Section 11.


6. ItemDefinitionSO — Field Reference

6.1 Base Fields

FieldTypeDescription
guidstringRead-only. Unique identifier for this asset. See Section 4.
displayNamestringThe name shown in the UI (e.g., "Brass Knuckles", "Bionic Heart").
descriptionstringThe tooltip text shown to the player. Write this to describe the first-stack effect; stacking behaviour is typically expressed inline (e.g., "Increase damage by 20% (+20% per stack).").
iconSpriteThe item sprite used in the inventory and shop UI. Assigned by the art/design team.
sfxPrefabGameObject(Optional) A sound effect prefab that plays when the item triggers. Leave blank if no unique SFX is needed.
maxStacksintThe maximum number of stacks this item can accumulate. Default is 999 (effectively unlimited). Set lower only when a hard cap is intended by design.
itemRarityEItemRarityThe rarity tier. Controls shop appearance and drop weighting. See Section 10.
itemCategoryEItemCategoryThe broad category used for sorting and UI grouping. See Section 10.

6.2 stack

Type: Stack (struct defined in ItemDefinitionSO.cs).

Defines how this item’s effect scales as stacks are gained. The formula is evaluated at runtime by Stack.CalculateStackFormula(float x, int max) where x is the current stack count.

Sub-fieldTypeDescription
stackTypeEStackTypeWhat the formula output represents — which value does stacking actually scale? See Section 7.2.
stackFormulaEStackFormulaThe mathematical formula used to compute the stacked value. See Section 7.1.
afloatThe first coefficient in the formula — typically the value at stack 1.
bfloatThe second coefficient in the formula — typically the per-stack increment or decay factor.

See Section 7 for full formula definitions and worked examples.

6.3 itemEffectConfigs

Type: ItemEffectConfig[]

An ordered array of effects that define what the item does and when. Every item needs at least one. The [Tooltip] in the source ("Order these conditions in the order you want them to check for activation") is important — the array is iterated in order, so place higher-priority or gating effects first.

Each ItemEffectConfig has the following fields:

Sub-fieldTypeDescription
effectSOItemEffectReference to the ItemEffect ScriptableObject containing the execution logic. A copy is instantiated at runtime so the original SO is never modified.
isMandatoryboolIf true, this effect always fires when the item activates, bypassing procChancePercentage and effectCondition. Use for effects that must be guaranteed (e.g., applying a status that is core to the item).
triggerProcsboolIf true, procs published inside this effect will notify other items. For example, if the effect deals damage, the resulting OnDamageDealt proc will trigger any OnDamageDealt items on both units. Leave false for most effects to prevent cascading proc loops — this is called out explicitly in the source comment.
rangeuintCell range used by certain effects that need a radius or target distance (e.g., an AOE heal). Default is 1.
triggerTypeEProcTriggerTypeThe event that activates this effect. Must match a proc that fires during gameplay. See Section 8.
procChancePercentagefloat (0 – 1)The probability that this effect executes when its trigger fires. 1.0 = 100%, 0.5 = 50%, etc. Ignored when isMandatory is true.
effectConditionEffectCondition(Optional) A condition SO that is evaluated before the effect fires. If the condition fails, the effect is skipped. Leave blank if the effect has no additional conditions. See Section 9.
effectParametersEffectParameters(Polymorphic via [SerializeReference]) The inline data values passed to the effect — things like damage amount, multipliers, or status references. The concrete type shown in the Inspector is determined by the selected effectSO.

Important

effectParameters stores data inline in the item asset via [SerializeReference]. The type must match what the effectSO expects. Type mismatches produce a NullReferenceException at runtime. If you change the effectSO, verify that the existing effectParameters are still the correct type.


7. Stacking System In-Depth

Every item has exactly one Stack configuration. The formula is applied whenever the game needs to know the current value for this item (e.g., how much damage bonus to add). x is always the current stack count (1-indexed — stack 1 is the first pick-up).

7.1 Stack Formulas

Linear

y = a + b * (x - 1)

Capped at maxStacks.

Each additional stack adds a flat b to the base value a. Stack 1 = a, Stack 2 = a + b, Stack 3 = a + 2b, and so on.

Example — Brass Knuckles (a = 30, b = 20):

StackValue
130
250
370

Use for: simple flat bonuses where each stack adds the same amount.


Hyperbolic

y = 1 - (1 - a) * (1 - b)^(x - 1)

Constraint: 0 ≤ a, b ≤ 1 (both inputs must be between 0 and 1).

Output approaches 1.0 asymptotically — it can never reach or exceed 100%. Each stack gives a smaller absolute gain than the last (diminishing returns). Stack 1 = a.

Example (a = 0.15, b = 0.10):

StackValue
10.150 (15%)
20.235 (23.5%)
30.312 (31.2%)

Use for: percentage-based stats where you want diminishing returns (e.g., dodge chance, damage reduction) to prevent 100% values.


Exponential

y = a * b^(x - 1)

Output multiplies by b with each stack. Stack 1 = a. Values grow very quickly for b > 1.

Example — Bionic Heart (a = 0.15, b = 1.15):

StackValue
10.150 (15%)
20.173 (17.3%)
30.198 (19.8%)
50.262 (26.2%)

Use for: effects that should grow faster the more you stack, or powerful/legendary items where late-game scaling is intentional.


Rational

y = (1 - a) * (1 - b)^(x + 1)

Constraint: 0 ≤ a, b ≤ 1.

Output decreases toward zero asymptotically — never reaches 0. Each stack reduces the value further. Used when a value should decay or diminish with stacking.

Use for: niche cases where increasing stacks should reduce a value (e.g., reducing a cooldown or penalty with diminishing effect).


7.2 Stack Types

EStackType tells the runtime what the formula output is used for. The value returned by CalculateStackFormula is applied differently depending on this setting.

ValueWhat is Scaled
DamageAmountFlat damage bonus added to hits from item effects.
AvoidDamageChanceChance (0–1) to avoid incoming damage entirely.
AddTargetsNumber of additional targets hit by the effect.
BaseStatsIncreaseMultiplier applied to the unit’s base stats.
DamageReductionMultiplierPercentage by which incoming damage is reduced.
HealthPercentAmount as a percentage of the unit’s max HP.
MultiplierBoostGeneral-purpose damage or effect multiplier.
FlatBoostGeneral-purpose flat bonus (context-dependent per effect).

7.3 Choosing the Right Formula

ScenarioRecommended Formula
Simple +X per stack (damage, flat stats)Linear
Percentage chance (dodge, proc chance) — needs diminishing returnsHyperbolic
Strong scaling, powerful late-game itemExponential
A value that decreases with stacksRational

8. Proc Trigger Types

triggerType on an ItemEffectConfig determines which in-game event activates the effect. Values are defined in the EProcTriggerType enum in ItemEffectConfig.cs.

ValueWhen it Fires
OnTurnStartAt the beginning of the unit’s turn.
OnTurnEndAt the end of the unit’s turn.
OnDamageDealtWhen this unit deals damage (before the damage is applied to the target).
OnPostDamageDealtWhen this unit deals damage (after the damage is applied to the target).
OnKillWhen this unit kills another unit.
OnPreDamageTakenWhen this unit is about to take damage (before it is applied).
OnPostDamageTakenWhen this unit takes damage (after it is applied).
OnStatusGainedWhen this unit gains a status effect.
OnStatusReducedWhen a status effect on this unit has its stack count reduced.
OnStatusChangedWhen any status effect on this unit changes (gained, reduced, or removed).
OnMovementWhen this unit moves to a new cell.
OnDeathWhen this unit dies.
OnItemGainedWhen this unit receives a new item.
OnPreHealTakenWhen this unit is about to receive healing (before it is applied).
OnPostHealTakenWhen this unit receives healing (after it is applied).
OnPreShieldTakenWhen this unit is about to receive shield (before it is applied).
OnPostShieldTakenWhen this unit receives shield (after it is applied).
OnHealGivenWhen this unit gives healing to another unit.
OnShieldGivenWhen this unit gives shield to another unit.

Note

The Pre vs Post distinction matters for items that modify values in-flight (e.g., a damage modifier must be OnDamageDealt / OnPreDamageTaken to affect the number before it is consumed). Items that react to the result use the Post variants.


9. Effect Conditions

EffectCondition is an abstract ScriptableObject (Assets/Scripts/Item System/Effects/EffectCondition.cs). It exposes a single method:

bool CheckCondition(IProc proc)

Concrete conditions live in Assets/Scripts/Item System/Conditions/ and their SO instances live in Assets/Conditions/. They are created via Create → Items → Conditions → [Condition Name].

Each ItemEffectConfig can hold one condition SO in its effectCondition field. If assigned, the condition is evaluated against the current proc before the effect fires. If it returns false, the effect is skipped (unless isMandatory is true).

If no condition is needed, leave the field blank.

To create a new condition type, see Creating a New Item Guide — the Effect Conditions section at the bottom covers the full workflow.


10. Enum Reference

EItemRarity

ValueTierNotes
Common1Simple, straightforward upgrades. Widely available in shops.
Rare2Moderately powerful, sometimes conditional.
Legendary3Powerful effects that can alter playstyle. Less frequent in shops.
Cursed4Extreme power with a significant drawback. Only available via random encounters/events, not shops.

EItemCategory

ValueMeaning
DamageItems that increase offensive output — bonus damage, additional targets, crit/kill effects.
DefenceItems that improve survivability — shields, damage reduction, healing effects, dodge.
UtilityItems that manipulate movement, turn economy, currency, or other non-combat factors.

11. Pre-Build Catalogue Validation

AssetCataloguePreBuildCheck runs automatically before every Unity build. For items it checks:

CatalogueKey
ItemsITEMS_CATALOGUE

If the count of ItemDefinitionSO assets in the project does not match the count registered in the catalogue, a dialog will appear. The recommended response is always Stop Build — then re-sync by opening the Item Catalogue SO, selecting Items in the Auto-Fill dropdown, and clicking Fill.

Shipping a build with a stale catalogue means newly created items will not be findable by their GUID at runtime.