How-To: Add Per-Item Logic
Goal: give a piece of gear behavior and state of its own by subclassing the equipment instance, and know exactly where those hooks run.
1. Create the instance subclass
One UCrimsonEquipmentInstance is created per equipped item and destroyed on unequip. Subclass it and point the definition's Instance Type at your class.
Right-click in the Content Browser -> Add -> Crimson Plugins -> Equipment -> Equipment Instance. Then open your definition and set Instance Type to the new class.
2. Use the lifecycle hooks
| Hook | Called | Override it to |
|---|---|---|
| OnEquipped | After the abilities are granted and the actors are spawned. | Start what the gear does while it is worn. |
| OnUnequipped | Before the actors are destroyed and the grants are revoked. | Undo exactly what OnEquipped did. |
Equip Item / Unequip Item, and again on each client when the instance replicates in or out (from the equipment list's PostReplicatedAdd and PreReplicatedRemove). Anything authoritative you put in OnEquipped - applying a gameplay effect, spawning a replicated actor, changing a stat - must be behind an authority branch, or every client will try to do it too.In your instance Blueprint, override the OnEquipped event. Start it with Get Pawn -> Has Authority (Branch) and put authoritative work on the True pin. Cosmetic work - a sound, a local VFX, a UI ping - belongs on the path that runs everywhere.
Mirror it in OnUnequipped: every authoritative operation started in OnEquipped is undone here, behind the same authority branch.
OnEquipped. It prints in both windows - once on the server when you equip, once on the client when the instance replicates in. The authority-gated branch prints only in the server window.3. Reach the wearer and the item
| Node | Returns | Notes |
|---|---|---|
| Get Pawn | APawn* | The owning pawn. The instance's outer is always the pawn. |
Get Typed Pawn (Pawn Type) | APawn* | The same pawn, already cast - returns null if it is not that class. No cast node needed in Blueprint. |
| Get Source Object | UObject* | Whatever was passed to Equip Item. Cast to your item type. |
| Get Definition | TSubclassOf<UCrimsonEquipmentDefinition> | The definition class this instance was created from. |
| Get Spawned Actors | TArray<AActor*> | This machine's attached actors. Local, per machine. |
SourceObject replicates, but a client only resolves it once the object itself has replicated to that machine. A runtime item instance that has not arrived yet reads as null. Never assume it is valid in a client-side OnEquipped; react to it arriving instead - see How-To: React to Equipment Changes.OnEquipped and valid shortly after.4. Add replicated state to the instance
UCrimsonEquipmentInstance is a replicated UObject registered as a subobject of the manager, so replicated properties you add on a subclass work the way they do on an actor component.
A Blueprint child of the instance cannot declare replicated variables - Blueprint variable replication is an actor feature. Per-item state that must reach clients belongs in a C++ subclass (the C++ tab), or on the source object your item system already replicates.
UCrimsonEquipmentManagerComponent registers each instance with AddReplicatedSubObject and also implements the legacy ReplicateSubobjects path, and the instance registers its own Iris fragments. Declaring the property and adding the DOREPLIFETIME line is the whole job.Current Durability follows it. Remove the DOREPLIFETIME line and the client value never moves - with no compile error.See also
- How-To: React to Equipment Changes
- How-To: Bridge an Item System
- Concept: Definitions, Instances and Entries