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
ItemEffectSO, etc.) see Creating a New Item Guide.
Table of Contents
- Overview
- Class Hierarchy
- Creating a New Item SO
- Assigning a GUID
- Registering in the Catalogue
- ItemDefinitionSO — Field Reference
- Stacking System In-Depth
- Proc Trigger Types
- Effect Conditions
- Enum Reference
- 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:
AssetIdentifierBaseSO—Assets/Scripts/Game Management/Asset Identifiers/AssetIdentifierBaseSO.csDefinitionSO—Assets/Scripts/DeveloperConsole/ConsoleCommands/DefinitionSO.csItemDefinitionSO—Assets/Scripts/Item System/ItemDefinitionSO.cs
3. Creating a New Item SO
- In the Project window, navigate to
Assets/Assets/Asset Identifier SOs/Items/. - Right-click → Create → Items → Item Definition.
- Name the asset to match the item’s display name.
Tip
Keep file names and
displayNamevalues 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:
- Select the item SO in the Project window.
- In the Inspector, right-click the component header (or use the three-dot menu) and choose Generate New GUID.
- The
guidfield will populate with a UUID v4 string (e.g.,ccfe8197-9aee-4ff5-b07c-44c8c5b63309). - Save the asset.
Warning
Never edit the
guidfield by hand. It is marked read-only in the Inspector for this reason. Never copy-paste a GUID from another SO — duplicate GUIDs will causeAssetCatalogueSO.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:
- Navigate to
Assets/Assets/Catalogues/and open the Item Catalogue asset. - In the Inspector, scroll to Auto-Fill Catalogue.
- Select Items from the dropdown.
- 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
| Field | Type | Description |
|---|---|---|
guid | string | Read-only. Unique identifier for this asset. See Section 4. |
displayName | string | The name shown in the UI (e.g., "Brass Knuckles", "Bionic Heart"). |
description | string | The 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)."). |
icon | Sprite | The item sprite used in the inventory and shop UI. Assigned by the art/design team. |
sfxPrefab | GameObject | (Optional) A sound effect prefab that plays when the item triggers. Leave blank if no unique SFX is needed. |
maxStacks | int | The maximum number of stacks this item can accumulate. Default is 999 (effectively unlimited). Set lower only when a hard cap is intended by design. |
itemRarity | EItemRarity | The rarity tier. Controls shop appearance and drop weighting. See Section 10. |
itemCategory | EItemCategory | The 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-field | Type | Description |
|---|---|---|
stackType | EStackType | What the formula output represents — which value does stacking actually scale? See Section 7.2. |
stackFormula | EStackFormula | The mathematical formula used to compute the stacked value. See Section 7.1. |
a | float | The first coefficient in the formula — typically the value at stack 1. |
b | float | The 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-field | Type | Description |
|---|---|---|
effectSO | ItemEffect | Reference to the ItemEffect ScriptableObject containing the execution logic. A copy is instantiated at runtime so the original SO is never modified. |
isMandatory | bool | If 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). |
triggerProcs | bool | If 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. |
range | uint | Cell range used by certain effects that need a radius or target distance (e.g., an AOE heal). Default is 1. |
triggerType | EProcTriggerType | The event that activates this effect. Must match a proc that fires during gameplay. See Section 8. |
procChancePercentage | float (0 – 1) | The probability that this effect executes when its trigger fires. 1.0 = 100%, 0.5 = 50%, etc. Ignored when isMandatory is true. |
effectCondition | EffectCondition | (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. |
effectParameters | EffectParameters | (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
effectParametersstores data inline in the item asset via[SerializeReference]. The type must match what theeffectSOexpects. Type mismatches produce aNullReferenceExceptionat runtime. If you change theeffectSO, verify that the existingeffectParametersare 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):
| Stack | Value |
|---|---|
| 1 | 30 |
| 2 | 50 |
| 3 | 70 |
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):
| Stack | Value |
|---|---|
| 1 | 0.150 (15%) |
| 2 | 0.235 (23.5%) |
| 3 | 0.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):
| Stack | Value |
|---|---|
| 1 | 0.150 (15%) |
| 2 | 0.173 (17.3%) |
| 3 | 0.198 (19.8%) |
| 5 | 0.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.
| Value | What is Scaled |
|---|---|
DamageAmount | Flat damage bonus added to hits from item effects. |
AvoidDamageChance | Chance (0–1) to avoid incoming damage entirely. |
AddTargets | Number of additional targets hit by the effect. |
BaseStatsIncrease | Multiplier applied to the unit’s base stats. |
DamageReductionMultiplier | Percentage by which incoming damage is reduced. |
HealthPercent | Amount as a percentage of the unit’s max HP. |
MultiplierBoost | General-purpose damage or effect multiplier. |
FlatBoost | General-purpose flat bonus (context-dependent per effect). |
7.3 Choosing the Right Formula
| Scenario | Recommended Formula |
|---|---|
| Simple +X per stack (damage, flat stats) | Linear |
| Percentage chance (dodge, proc chance) — needs diminishing returns | Hyperbolic |
| Strong scaling, powerful late-game item | Exponential |
| A value that decreases with stacks | Rational |
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.
| Value | When it Fires |
|---|---|
OnTurnStart | At the beginning of the unit’s turn. |
OnTurnEnd | At the end of the unit’s turn. |
OnDamageDealt | When this unit deals damage (before the damage is applied to the target). |
OnPostDamageDealt | When this unit deals damage (after the damage is applied to the target). |
OnKill | When this unit kills another unit. |
OnPreDamageTaken | When this unit is about to take damage (before it is applied). |
OnPostDamageTaken | When this unit takes damage (after it is applied). |
OnStatusGained | When this unit gains a status effect. |
OnStatusReduced | When a status effect on this unit has its stack count reduced. |
OnStatusChanged | When any status effect on this unit changes (gained, reduced, or removed). |
OnMovement | When this unit moves to a new cell. |
OnDeath | When this unit dies. |
OnItemGained | When this unit receives a new item. |
OnPreHealTaken | When this unit is about to receive healing (before it is applied). |
OnPostHealTaken | When this unit receives healing (after it is applied). |
OnPreShieldTaken | When this unit is about to receive shield (before it is applied). |
OnPostShieldTaken | When this unit receives shield (after it is applied). |
OnHealGiven | When this unit gives healing to another unit. |
OnShieldGiven | When this unit gives shield to another unit. |
Note
The
PrevsPostdistinction matters for items that modify values in-flight (e.g., a damage modifier must beOnDamageDealt/OnPreDamageTakento affect the number before it is consumed). Items that react to the result use thePostvariants.
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
| Value | Tier | Notes |
|---|---|---|
Common | 1 | Simple, straightforward upgrades. Widely available in shops. |
Rare | 2 | Moderately powerful, sometimes conditional. |
Legendary | 3 | Powerful effects that can alter playstyle. Less frequent in shops. |
Cursed | 4 | Extreme power with a significant drawback. Only available via random encounters/events, not shops. |
EItemCategory
| Value | Meaning |
|---|---|
Damage | Items that increase offensive output — bonus damage, additional targets, crit/kill effects. |
Defence | Items that improve survivability — shields, damage reduction, healing effects, dodge. |
Utility | Items 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:
| Catalogue | Key |
|---|---|
| Items | ITEMS_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.