docs: Update item pickup setup instructions and add game examples for Blueprint walkthroughs
This commit is contained in:
@@ -46,23 +46,180 @@ Based on `Item Type`, fill the relevant sub-struct (other sub-panels auto-hide v
|
||||
| `Ammo` | `AmmoData` (legacy) | AmmoTypeTag, PerPickupCount |
|
||||
| `KeyItem`, `Document`, `Collectible`, `Resource`, `Misc` | None — core properties only | |
|
||||
|
||||
### Step 4 — Place a Pickup in the World
|
||||
### Step 4 — Build the BP_ItemPickup Blueprint (one-time)
|
||||
|
||||
The Data Asset does **not** appear in the world. To spawn it:
|
||||
The Data Asset does **not** appear in the world. You need a Blueprint Actor that references it. Here is the exact setup:
|
||||
|
||||
1. Create a `BP_ItemPickup` actor (see spec #25: [`../../04-inventory/25_BP_ItemPickup.md`](../04-inventory/25_BP_ItemPickup.md))
|
||||
2. In the `BP_ItemPickup` actor instance, set `Config → Item Data` → your `DA_Item_MedKit`
|
||||
3. Drag `BP_ItemPickup` into the level
|
||||
4. The pickup reads the mesh from the Data Asset, handles overlap, and calls `BPC_InventorySystem.AddItem(ItemData)` on interact
|
||||
#### 4.1 — Create the Blueprint
|
||||
|
||||
```
|
||||
DA_Item_MedKit (Content Browser) ← defines WHAT the item is
|
||||
Content Browser → Framework/Inventory/
|
||||
Right-click → Blueprint Class → Actor
|
||||
Name: BP_ItemPickup
|
||||
```
|
||||
|
||||
#### 4.2 — Add Components
|
||||
|
||||
Open `BP_ItemPickup` → **Viewport** tab → **Add Component** (top-left button):
|
||||
|
||||
| # | Component Class | Name | Purpose |
|
||||
|---|----------------|------|---------|
|
||||
| 1 | `StaticMeshComponent` | `Mesh` | Renders the item's 3D model in the world |
|
||||
| 2 | `SphereComponent` | `InteractionCollision` | Detects when the player is near enough to pick up |
|
||||
| 3 | *(optional)* `AudioComponent` | `PickupSound` | Plays a sound when collected |
|
||||
|
||||
**Select `InteractionCollision` → Details panel:**
|
||||
- `Sphere Radius` → `150.0` (how close the player must be)
|
||||
- Under **Collision Presets** → set to `OverlapOnlyPawn` (only the player triggers it)
|
||||
|
||||
#### 4.3 — Create the Config Variable
|
||||
|
||||
1. In the **My Blueprint** panel (left side), click **+ Variable**
|
||||
2. Name: `Config`
|
||||
3. Variable Type: **Struct → `S_PickupConfig`** (you may need to create this struct first — see spec #25 for its fields)
|
||||
|
||||
If `S_PickupConfig` doesn't exist yet, create it manually:
|
||||
```
|
||||
Content Browser → Framework/Inventory/
|
||||
Right-click → Blueprints → Structure
|
||||
Name: S_PickupConfig
|
||||
Add fields:
|
||||
ItemData → Type: DA_ItemData (Object Reference)
|
||||
Quantity → Type: Integer, default: 1
|
||||
bAutoRotate → Type: Boolean, default: true
|
||||
bBobUpDown → Type: Boolean, default: true
|
||||
BobAmplitude → Type: Float, default: 10.0
|
||||
BobFrequency → Type: Float, default: 1.0
|
||||
```
|
||||
|
||||
4. After creating the variable, select it → Details panel:
|
||||
- **Instance Editable** → ✓ checked (so you can set it per-instance in the level)
|
||||
- **Category** → `Pickup Config`
|
||||
- **Tooltip** → "The item data asset this pickup represents"
|
||||
|
||||
#### 4.4 — Wire the Construction Script
|
||||
|
||||
Go to the **Construction Script** tab (or open the Construction Script graph). This runs every time you change the Config in the editor, so the mesh updates immediately.
|
||||
|
||||
```
|
||||
Construction Script
|
||||
│
|
||||
├─ Get Config → Break S_PickupConfig → ItemData
|
||||
│ │
|
||||
│ ├─ Is Valid (ItemData)?
|
||||
│ │ ├─ True → continue
|
||||
│ │ └─ False → Print String "No ItemData assigned" (Editor-only) → Return
|
||||
│ │
|
||||
│ └─ ItemData → Get World Mesh (this is a soft reference — may not be loaded)
|
||||
│ │
|
||||
│ ├─ Is Valid (WorldMesh)?
|
||||
│ │ ├─ True:
|
||||
│ │ │ → Set Static Mesh (Mesh component, New Mesh = WorldMesh)
|
||||
│ │ │ → ItemData → Get Display Name → Set Actor Label
|
||||
│ │ └─ False:
|
||||
│ │ → ItemData → World Mesh → Async Load Asset
|
||||
│ │ → On Load Complete → Set Static Mesh
|
||||
│ │
|
||||
│ └─ ItemData → Get Icon → (cache for UI prompt)
|
||||
```
|
||||
|
||||
**Key node-by-node:**
|
||||
1. Drag the `Config` variable from My Blueprint → **Get Config**
|
||||
2. **Break S_PickupConfig** (right-click the pin → Split Struct Pin, or drag off → "Break")
|
||||
3. From the `ItemData` pin, drag off → Create a `IsValid` node
|
||||
4. From the valid `ItemData` output, drag off → type `Get World Mesh` (this appears because `WorldMesh` is a `UPROPERTY` on `DA_ItemData`; if using soft reference, you'll get a `TSoftObjectPtr<UStaticMesh>` — connect to **Async Load Asset** or **Load Synchronous** for Construction Script)
|
||||
5. From the resolved mesh, connect to `Set Static Mesh` node → target is the `Mesh` component (drag Mesh from the Components panel into the graph → Get)
|
||||
|
||||
#### 4.5 — Wire Interaction (I_Interactable)
|
||||
|
||||
**Step A — Add the Interface:**
|
||||
1. **Class Settings** (toolbar button) → **Interfaces** → **Add** → select `UInteractable` (the C++ interface from `I_InterfaceLibrary.h`)
|
||||
2. Compile. Now `Interact`, `Can Interact`, `Get Interaction Prompt` events appear in the right-click menu.
|
||||
|
||||
**Step B — Wire the Events:**
|
||||
|
||||
```
|
||||
Event Interact (from I_Interactable)
|
||||
│ Interactor: AActor*
|
||||
│
|
||||
├─ Get Config → Break → ItemData
|
||||
│
|
||||
├─ Interactor → Get Component by Class (BPC_InventorySystem)
|
||||
│ │
|
||||
│ └─ Is Valid?
|
||||
│ ├─ False → Return (no inventory system on interactor)
|
||||
│ └─ True → InventorySystem
|
||||
│ │
|
||||
│ ├─ Call Can Add Item(ItemData, Quantity from Config)
|
||||
│ │ │
|
||||
│ │ ├─ False → Print "Inventory Full" → Return
|
||||
│ │ └─ True:
|
||||
│ │ ├─ Call Add Item(ItemData, Quantity)
|
||||
│ │ ├─ Play Sound at Location (PickupSound, GetActorLocation)
|
||||
│ │ ├─ Destroy Actor
|
||||
│ │ └─ Return
|
||||
│ │
|
||||
│ └─ (If ItemData has bIsInfinite or respawn logic — skip Destroy)
|
||||
|
||||
Event Can Interact (from I_Interactable)
|
||||
│ Interactor, OutBlockReason (by ref)
|
||||
│
|
||||
├─ Is Config.ItemData Valid?
|
||||
│ ├─ False → OutBlockReason = "No item data" → Return False
|
||||
│ └─ True → Return True
|
||||
|
||||
Event Get Interaction Prompt (from I_Interactable)
|
||||
│
|
||||
├─ Get Config → ItemData → Get Display Name
|
||||
└─ Return "Pick up [ItemName]"
|
||||
```
|
||||
|
||||
#### 4.6 — Add Bobbing Rotation (optional polish)
|
||||
|
||||
In **Event Graph → Event BeginPlay**:
|
||||
|
||||
```
|
||||
Event BeginPlay
|
||||
│
|
||||
├─ Get Config → Break → bAutoRotate
|
||||
│ └─ True → Add Timeline → name: "BobAndRotate"
|
||||
│ ├─ Update track:
|
||||
│ │ ├─ Mesh → Add World Rotation (DeltaRotation = 0,0,Timeline.Rotation * 90)
|
||||
│ │ └─ Mesh → Add World Offset (Delta = 0,0,Timeline.Bob * BobAmplitude * sin(time), ...)
|
||||
│ │
|
||||
│ └─ Timeline: float track 0→1 looping over 2 seconds
|
||||
├─ Enable collision on InteractionCollision
|
||||
└─ Bind OnComponentBeginOverlap(InteractionCollision) → Highlight mesh, show prompt
|
||||
```
|
||||
|
||||
#### 4.7 — Compile and Use
|
||||
|
||||
1. **Compile → Save**
|
||||
2. **Drag `BP_ItemPickup` into your level**
|
||||
3. Select the instance → Details panel → **Pickup Config → Item Data** → select `DA_Item_MedKit`
|
||||
4. Set `Quantity` → `1` (or more for stacked items)
|
||||
5. The **Construction Script** runs immediately — the mesh should appear in the viewport
|
||||
6. Position the actor where you want it
|
||||
|
||||
**Verification in PIE (Play In Editor):**
|
||||
- The pickup should show its mesh, slowly rotating
|
||||
- Walk up to it — the overlap event fires
|
||||
- Press Interact — item goes into inventory, pickup disappears
|
||||
- Open inventory → item should be in a slot with the correct name and icon
|
||||
|
||||
```
|
||||
DA_Item_MedKit (Content Browser) ← defines IDENTITY
|
||||
↑ referenced by
|
||||
BP_ItemPickup (Actor in level) ← physical body in the world
|
||||
BP_ItemPickup (Actor in level) ← physical BODY in world
|
||||
├── StaticMeshComponent "Mesh" ← renders WorldMesh from Data Asset
|
||||
├── SphereComponent "Collision" ← detects player proximity
|
||||
└── Config struct ← holds pointer to DA_ItemData + quantity
|
||||
↑ interacts via
|
||||
BPC_InteractionDetector → BPC_InventorySystem.AddItem()
|
||||
BPC_InteractionDetector → I_Interactable → BPC_InventorySystem.AddItem()
|
||||
```
|
||||
|
||||
> **For concrete, step-by-step examples** of building specific item types (flashlight, pistol, medkit, keycard) with complete Blueprint graphs, component lists, and wiring diagrams, see the [`docs/game/`](../../game/README.md) directory.
|
||||
|
||||
---
|
||||
|
||||
## Single Identity Tag — Why One Tag Is Enough
|
||||
|
||||
Reference in New Issue
Block a user