8.7 KiB
Item Example — Keycard (Key Item)
Item Type: KeyItem
Complexity: Low
Systems Used: DA_ItemData, BP_ItemPickup, BPC_InventorySystem, BPC_KeyItemSystem, I_Lockable, BP_DoorActor
What You Learn: Key item Data Asset, auto-protection from drop/clear, used-once pattern, door unlocking via I_Lockable
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_Keycard_Omega
1.2 — Fill Properties
| Property | Value | Notes |
|---|---|---|
Item Tag |
Framework.Item.KeyItem.KeycardOmega |
Unique — registered in DA_GameTagRegistry |
Display Name |
"Omega Keycard" | Player sees this |
Description |
"A high-security keycard labeled 'Omega Wing.'" | Shown in journal/inventory |
Icon |
T_Keycard_Icon |
Card-shaped texture |
World Mesh |
SM_Keycard |
Flat card mesh |
Weight |
0.1 |
Very light |
Stack Limit |
1 |
One per slot — cannot stack keycards |
Item Type |
KeyItem |
Key items are auto-protected |
b Is Key Item |
✓ (checked) | This property also appears — it's a boolean flag |
b Can Be Dropped |
✗ (unchecked) | Key items should NOT be droppable (auto-forced by bIsKeyItem) |
1.3 — Save
No sub-data needed. Key items don't have Equipment or Consumable data.
2. Create the BP_Pickup_KeycardOmega
Same pattern as other pickups:
2.1 — Create Blueprint
Content Browser → Game/Pickups/
Right-click → Blueprint Class → Actor
Name: BP_Pickup_KeycardOmega
2.2 — Components
| # | Component | Name | Purpose |
|---|---|---|---|
| 1 | StaticMeshComponent |
Mesh |
Card model |
| 2 | SphereComponent |
PickupTrigger |
Radius 150, OverlapOnlyPawn |
2.3 — Variable
ItemData → Type: DA_ItemData → Object Reference → Instance Editable ✓
2.4 — Construction Script (same pattern)
ItemData → Get World Mesh → Load Synchronous → Set Static Mesh (Mesh)
ItemData → Get Display Name → Set Actor Label
2.5 — I_Interactable Wiring (same pattern)
Interactor → Get BPC_InventorySystem → CanAddItem(ItemData, 1)
True → AddItem → Destroy Actor → Return True
False → Print "Inventory Full" → Return False
3. Create the Lockable Door
3.1 — Create Door Blueprint
Content Browser → Game/Actors/
Right-click → Blueprint Class → Actor (or BP_DoorActor from framework)
Name: BP_Door_OmegaWing
3.2 — Add Components
| # | Component | Name | Purpose |
|---|---|---|---|
| 1 | StaticMeshComponent |
DoorFrame |
The door frame (static) |
| 2 | StaticMeshComponent |
DoorPanel |
The moving door part |
| 3 | BoxComponent |
InteractionTrigger |
Door interaction range |
3.3 — Add Interfaces
Class Settings → Interfaces → Add:
UInteractableULockable
3.4 — Variables
| Variable | Type | Default | Purpose |
|---|---|---|---|
bIsLocked |
Boolean | true |
Door starts locked |
bIsOpen |
Boolean | false |
Door starts closed |
RequiredKeyTag |
GameplayTag | Framework.Item.KeyItem.KeycardOmega |
Which key unlocks this |
3.5 — Wire I_Lockable
Event Try Unlock (Interface -> ULockable)
│ Unlocker: AActor*, KeyTag: FGameplayTag
│ Return Boolean
│
├─ bIsLocked? → Branch
│ ├─ True:
│ │ ├─ KeyTag == RequiredKeyTag? → Branch
│ │ │ ├─ True:
│ │ │ │ ├─ Set bIsLocked = false
│ │ │ │ ├─ Unlocker → Get BPC_KeyItemSystem
│ │ │ │ │ └─ Consume Key (KeyTag) ← removes key from inventory
│ │ │ │ ├─ Print "Door unlocked with Omega Keycard"
│ │ │ │ └─ Return True
│ │ │ │
│ │ │ └─ False:
│ │ │ ├─ Print "Wrong key — requires Omega Keycard"
│ │ │ └─ Return False
│ │ │
│ │ └─ False: (already unlocked)
│ │ └─ Return True
Event Is Locked
│ Return Boolean
└─ Return bIsLocked
Event Get Required Key Tag
│ Return FGameplayTag
└─ Return RequiredKeyTag
Event Try Lock
│ Locker: AActor*
│ Return Boolean
└─ Set bIsLocked = true → Return True (re-lockable for puzzle purposes)
3.6 — Wire I_Interactable (on door)
Event Interact (Interface -> UInteractable)
│ Interactor: AActor*
│ Return Boolean
│
├─ bIsLocked? → Branch
│ ├─ True:
│ │ ├─ Interactor → Get BPC_KeyItemSystem
│ │ │ └─ Has Key(RequiredKeyTag)?
│ │ │ ├─ True:
│ │ │ │ ├─ Call Try Unlock (self, Interactor, RequiredKeyTag)
│ │ │ │ └─ (If unlocked) → Open Door (see below)
│ │ │ │
│ │ │ └─ False:
│ │ │ ├─ Print "Door is locked. Find Omega Keycard."
│ │ │ └─ Return False
│ │ │
│ │ └─ Return False
│ │
│ └─ False: (door is unlocked)
│ ├─ bIsOpen? → Branch
│ │ ├─ True → Close Door → Return True
│ │ └─ False → Open Door → Return True
Function: Open Door
│
├─ Timeline (Rotation track, 0 → OpenAngle over OpenDuration)
│ └─ Update: DoorPanel → Set Relative Rotation
├─ Set bIsOpen = true
└─ (Optional) Play door creak sound
Function: Close Door
│
├─ Timeline (Rotation track, OpenAngle → 0 over CloseDuration)
│ └─ Update: DoorPanel → Set Relative Rotation
├─ Set bIsOpen = false
└─ (Optional) Play door close sound
4. Wire BPC_KeyItemSystem (On Player Pawn)
The BPC_KeyItemSystem tracks which key items the player holds. It automates:
- Protecting key items from being dropped/cleared
- Validating key item requirements on door/lock interactions
- Removing consumed key items after use
In your BP child of BPC_KeyItemSystem:
Function: Has Key (KeyTag: GameplayTag) → Boolean
│
├─ Get Owner → Get BPC_InventorySystem
├─ Get All Items → For Each Loop
│ ├─ Item → Get bIsKeyItem → Branch
│ │ ├─ True: Item → Get ItemTag == KeyTag? → Return True
│ │ └─ False: Continue
│ │
│ └─ Loop end → Return False
Function: Consume Key (KeyTag: GameplayTag)
│
├─ Get Owner → Get BPC_InventorySystem
├─ Has Key(KeyTag)? → Branch
│ ├─ True: Inventory → Remove Item (by KeyTag, Quantity=1)
│ └─ False: Print "No such key in inventory"
In the full framework,
BPC_KeyItemSystemalso preventsClear InventoryandDropoperations from affecting key items by checkingbIsKeyItemon the Data Asset.
5. Verification Checklist
Step 1 — Pickup:
BP_Pickup_KeycardOmegaplaced in level, mesh visible- Walk up → prompt "Pick up Omega Keycard" → press Interact → card goes to inventory
Step 2 — Inventory Protection:
- Keycard appears in inventory with "KEY" badge/indicator
- Try to drop keycard → blocked (cannot drop key items)
- Try "Clear Inventory" → keycard remains (protected)
Step 3 — Door Interaction:
- Walk up to
BP_Door_OmegaWingwhile locked → prompt "Door is locked" - Interact → door stays closed, shows "Requires Omega Keycard"
- Pick up keycard → walk to door → interact → door unlocks, keycard consumed from inventory
- Interact again → door opens
Step 4 — Wrong Key:
- Create a
DA_Item_Keycard_Betawith a different tag - Pick it up, try on Omega door → "Wrong key — requires Omega Keycard"
- Keycard_Beta stays in inventory (not consumed on wrong door)
6. KeyItem vs Regular Item — What's Different
| Behavior | Regular Item | Key Item (bIsKeyItem = true) |
|---|---|---|
| Can be dropped? | Yes (if bCanBeDropped) |
No (auto-protected) |
| Can be cleared (death/new game)? | Yes | No (preserved across death) |
| Stacks | Yes (up to StackLimit) | Usually StackLimit=1 |
| Appears in inventory? | Yes | Yes, with KEY indicator |
| Consumed on use? | Depends on type | Yes (used once, then removed) |
| Sells to vendor? | Yes | No (protected from sale) |
Key items exist specifically to gate progression. They're a player's permanent proof of having solved a puzzle, explored an area, or defeated a boss. The framework ensures they can't be accidentally lost.