Files
UE5-Modular-Game-Framework/docs/game/item-keycard.md

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:

  • UInteractable
  • ULockable

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_KeyItemSystem also prevents Clear Inventory and Drop operations from affecting key items by checking bIsKeyItem on the Data Asset.


5. Verification Checklist

Step 1 — Pickup:

  • BP_Pickup_KeycardOmega placed 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_OmegaWing while 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_Beta with 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.