7.2 KiB
Item Example — MedKit (Consumable)
Item Type: Consumable
Complexity: Low
Systems Used: DA_ItemData, BP_ItemPickup, BPC_InventorySystem, BPC_ConsumableSystem, BPC_HealthSystem
What You Learn: Consumable Data Asset, pickup actor, health restore, stackable item, quick-slot use
1. Create the DA_ItemData
1.1 — Create the Data Asset
Content Browser → Game/Items/
Right-click → Miscellaneous → Data Asset
Class: DA_ItemData
Name: DA_Item_MedKit
1.2 — Fill Core Properties
| Property | Value | Notes |
|---|---|---|
Item Tag |
Framework.Item.Consumable.MedKit |
Unique identity |
Display Name |
"MedKit" | Player sees this |
Description |
"A standard medical kit. Restores 25 health." | Shown in inventory |
Icon |
T_MedKit_Icon |
Any red/white cross texture for prototype |
World Mesh |
SM_MedKit |
Soft reference — Construction Script resolves it |
Weight |
1.0 |
Light carry weight |
Stack Limit |
5 |
Can carry up to 5 in one stack |
Item Type |
Consumable |
Triggers Consumable Data panel |
1.3 — Fill Consumable Data
When ItemType == Consumable, the Consumable Data panel appears:
| Field | Value | Notes |
|---|---|---|
Health Restore |
25.0 |
How much HP to restore (0-100 clamp) |
Stress Reduce |
0.0 |
Optional stress relief |
Use Duration |
2.0 |
Seconds to consume (animation time) |
bConsumedOnUse |
✓ (true) | Item is removed from inventory after use |
1.4 — Save
The Data Asset is ready. No other config needed for a simple consumable.
2. Create the BP_Pickup_MedKit
Follow the same pattern as the flashlight pickup, but simpler — no active-use actor needed.
2.1 — Create Blueprint
Content Browser → Game/Pickups/
Right-click → Blueprint Class → Actor
Name: BP_Pickup_MedKit
2.2 — Add Components
| # | Component | Name | Purpose |
|---|---|---|---|
| 1 | StaticMeshComponent |
Mesh |
Renders the medkit model |
| 2 | SphereComponent |
PickupTrigger |
Interaction radius (Sphere Radius → 150) |
Select PickupTrigger → Details → Collision Presets → OverlapOnlyPawn
2.3 — Create ItemData Variable
+ Variable → Name: ItemData → Type: DA_ItemData → Object Reference
Select the variable → Details:
- Instance Editable → ✓
- Category →
Pickup
2.4 — Wire Construction Script
[Construction Script]
│
├─ ItemData → Is Valid? → Branch
│ ├─ True:
│ │ ├─ ItemData → Get World Mesh → Load Synchronous → Set Static Mesh (Mesh)
│ │ └─ ItemData → Get Display Name → Set Actor Label
│ └─ False:
│ └─ Print String ("No ItemData assigned to BP_Pickup_MedKit")
2.5 — Add I_Interactable and Wire
Same pattern as flashlight. The key difference for consumables is stacking: the pickup can hold multiple units.
Event Interact
│ Interactor: AActor*
│
├─ Interactor → Get Component by Class (UBPC_InventorySystem) → Is Valid?
│ │
│ └─ True → [Inventory]
│ │
│ ├─ Can Add Item(ItemData, Quantity=1)
│ │ │
│ │ ├─ True → Add Item(ItemData, Quantity=1) → Destroy Actor → Return True
│ │ │
│ │ └─ False:
│ │ ├─ Print "Inventory Full"
│ │ └─ Return False
For multi-pickup stacks (e.g., picking up 3 medkits at once), set a
Quantityvariable (Integer, Instance Editable) and pass it toAdd Item. The inventory auto-stacks identical items.
2.6 — Add Bobbing (optional)
Add a Timeline to Event BeginPlay with a sine wave for Z offset — same as flashlight example.
3. Wire Consumable Use (On Player Pawn)
When the player uses a consumable from their inventory or quick-slot:
3.1 — In BPC_ConsumableSystem (BP child on pawn)
Event Use Consumable (custom event)
│ ItemData: DA_ItemData*
│
├─ ItemData → Get Consumable Data (Break FItemConsumableData)
│ │
│ ├─ Health Restore > 0?
│ │ └─ True:
│ │ ├─ Get Owner → Get Component by Class (UBPC_HealthSystem)
│ │ │ │
│ │ │ └─ Is Valid? → True:
│ │ │ └─ Apply Healing (HealthRestore, Healer=self)
│ │ │ │
│ │ │ └─ Print String: "Restored {HealthRestore} HP"
│ │ │
│ │ └─ False: Print "No HealthSystem found"
│ │
│ ├─ Stress Reduce > 0?
│ │ └─ True:
│ │ └─ Get BPC_StressSystem → Remove Stress (StressReduce)
│ │
│ ├─ bConsumedOnUse?
│ │ └─ True:
│ │ └─ Get BPC_InventorySystem → Remove Item (ItemData, 1)
│ │
│ └─ (Optional) Play sound, screen effect, widget animation
3.2 — Quick Test Without Full Integration
Bind a test key (e.g., IA_UseItem) in your player character:
Event InputAction (IA_UseItem, Pressed)
│
├─ Get Component by Class (UBPC_InventorySystem)
├─ Get All Items → For Each Loop
│ │
│ ├─ Break FInventorySlot → Item
│ ├─ Item → Get Item Type == Consumable?
│ │ └─ True:
│ │ ├─ Item → Get Consumable Data → Health Restore
│ │ ├─ Get BPC_HealthSystem → Apply Healing (HealthRestore)
│ │ ├─ Inventory → Remove Item (Item, 1)
│ │ └─ Break (exit loop — only use one)
│ │
│ └─ Continue loop
4. Verification Checklist
- Data Asset:
DA_Item_MedKithasItemType = Consumable,HealthRestore = 25,StackLimit = 5 - Pickup in level: Mesh appears, bobs, interaction prompt shows "Pick up MedKit"
- Inventory: Pick up medkit → appears in inventory slot. Pick up 4 more → they stack (quantity = 5). Pick up 6th → fails (stack limit).
- Use: Press use item key → health increases by 25, stack count decreases by 1
- Weight: Each medkit adds 1.0 to carry weight.
Get Remaining Weightdecreases by 1.0 per pickup. - Full inventory: Pick up medkit when no slots left → "Inventory Full" feedback, pickup remains in world
5. Key Concepts
| Concept | How It Works |
|---|---|
| Stacking | StackLimit = 5 on the Data Asset. BPC_InventorySystem.AddItem() auto-finds existing stacks and adds to them instead of creating new slots. |
| Consumed on use | bConsumedOnUse = true → BPC_ConsumableSystem calls RemoveItem() after applying effects. Set to false for reusable items (e.g., a reusable syringe with cooldown). |
| Soft references | WorldMesh is a TSoftObjectPtr<UStaticMesh> — it doesn't load into memory until Construction Script resolves it. This keeps memory low when assets aren't in use. |
| Inventory weight | BPC_InventorySystem.CurrentWeight auto-updates when items are added/removed. CanAddItem() checks weight capacity before pickup. |