add blueprints

This commit is contained in:
Lefteris Notas
2026-05-19 13:22:27 +03:00
parent f71bc678b2
commit 411edea8ce
138 changed files with 23330 additions and 0 deletions

View File

@@ -0,0 +1,382 @@
# 16 — Interaction Detector (`BPC_InteractionDetector`)
## Purpose
The player's "interaction eye" — performs trace-based detection of interactable objects in the world, sorts them by priority/distance, tracks the current best target, and manages the interaction prompt widget. Every interactive system in the game funnels through this component.
## Dependencies
- **Requires:** `I_Interactable` (interface on all interactable actors), `PlayerCameraManager` (for trace origin), `BPC_MovementStateSystem` (block interaction during specific states)
- **Required By:** `WBP_InteractionPrompt` (HUD element), `BPC_PickupComponent`, `BPC_InteractableDoorComponent`, `BPC_LeverPuzzleComponent`
- **Engine/Plugin Requirements:** `LineTraceByChannel` (ECC_GameTraceChannel1 = Interaction), `TimerHandle` for scan interval
## Class Info
| Property | Value |
|----------|-------|
| **Parent Class** | `ActorComponent` |
| **Class Type** | Blueprint Component |
| **Asset Path** | `Content/Framework/Interaction/BPC_InteractionDetector` |
| **Implements Interfaces** | None |
---
## 1. Enums
### `E_InteractionInputMode`
| Value | Description |
|-------|-------------|
| `Press = 0` | Single press to interact |
| `Hold = 1` | Hold over duration to confirm |
| `DoubleTap = 2` | Two rapid presses |
| `Auto = 3` | Automatic on proximity (no input) |
### `E_InteractionPriority`
| Value | Description |
|-------|-------------|
| `Low = 0` | Ambient / cosmetic items |
| `Normal = 1` | Standard pickups, doors |
| `High = 2` | Story-critical, puzzles |
| `Emergency = 3` | Immediate threat (hide spot, weapon) |
### `E_DetectionState`
| Value | Description |
|-------|-------------|
| `NoTarget = 0` | Nothing in range |
| `TargetInRange = 1` | Potential target found |
| `TargetConfirmed = 2` | Best target selected |
| `Interacting = 3` | Currently performing interaction |
---
## 2. Structs
### `S_InteractableTarget`
| Field | Type | Description |
|-------|------|-------------|
| `TargetActor` | `AActor` | The interactable actor |
| `InterfaceRef` | `I_Interactable` | Cast to interface |
| `Priority` | `E_InteractionPriority` | Priority level |
| `Distance` | `Float` | Distance from player to target |
| `InteractionLabel` | `FText` | Display name (e.g. "Open Door", "Pick Up Key") |
| `InputMode` | `E_InteractionInputMode` | How interaction is triggered |
| `HoldDuration` | `Float` | Seconds required if InputMode is Hold |
| `bIsHighlighted` | `Boolean` | Whether target is visually highlighted |
| `TargetLocation` | `Vector` | World location for UI widget |
### `S_InteractionResult`
| Field | Type | Description |
|-------|------|-------------|
| `bSuccess` | `Boolean` | Whether interaction was successful |
| `FailureReason` | `FText` | Human-readable failure reason |
| `TargetActor` | `AActor` | The interacted actor |
| `ContextTag` | `GameplayTag` | Tag for event recording |
---
## 3. Variables
### Configuration (Instance Editable, Expose On Spawn)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `InteractionRange` | `Float` | `250.0` | `Detection Config` | Max trace distance (cm) |
| `DetectionAngle` | `Float` | `45.0` | `Detection Config` | Cone half-angle for detection (degrees) |
| `TraceRadius` | `Float` | `10.0` | `Detection Config` | Sphere trace radius |
| `ScanInterval` | `Float` | `0.1` | `Detection Config` | Seconds between detection scans |
| `MaxTargetsInRange` | `Integer` | `16` | `Detection Config` | Max detected targets per scan |
| `bShowDebugTrace` | `Boolean` | `false` | `Detection Config` | Visualise trace in editor |
| `TraceChannel` | `TEnumAsByte<ECollisionChannel>` | `ECC_GameTraceChannel1` | `Detection Config` | Collision channel for interaction |
| `bBlockDuringDeath` | `Boolean` | `true` | `Detection Config` | Block interaction while dead |
| `bBlockDuringHiding` | `Boolean` | `true` | `Detection Config` | Block interaction while hidden |
| `bBlockDuringCombat` | `Boolean` | `false` | `Detection Config` | Block interaction during combat |
### Internal (Private / Protected, No Expose)
| Variable | Type | Default | Category | Description |
|----------|------|---------|----------|-------------|
| `BestTargetIndex` | `Integer` | `-1` | `Detection State` | Index of currently selected target |
| `DetectedTargets` | `Array<S_InteractableTarget>` | `[]` | `Detection State` | All detected targets this scan |
| `CurrentTarget` | `S_InteractableTarget` | `-` | `Detection State` | Currently selected best target |
| `DetectionState` | `E_DetectionState` | `NoTarget` | `Detection State` | Current state of the detector |
| `bIsPerformingInteraction` | `Boolean` | `false` | `Detection State` | Whether interaction is in progress |
| `HoldInteractionProgress` | `Float` | `0.0` | `Detection State` | Progress for hold-type interactions |
| `OwnerPlayerController` | `APlayerController` | `None` | `Cache` | Cached player controller |
| `OwnerCameraManager` | `APlayerCameraManager` | `None` | `Cache` | Cached camera manager |
| `ScanTimerHandle` | `FTimerHandle` | `-` | `Timing` | Timer for scan interval |
| `DetectedActors_LastFrame` | `Set<AActor>` | `{}` | `Tracking` | Previous frame targets for enter/exit detection |
### Replicated (if multiplayer)
| Variable | Type | Condition | Description |
|----------|------|-----------|-------------|
| `CurrentTarget` | `S_InteractableTarget` | `Replicated` | Synced selected target |
---
## 4. Functions
### Public Functions
#### `StartDetection` → `void`
- **Description:** Begins the scan loop for interactable targets.
- **Parameters:** None
- **Flow:**
1. Get owner Player Controller
2. Get Player Camera Manager
3. Start scan timer (ScanInterval)
4. If bShowDebugTrace: enable debug line visualisation
#### `StopDetection` → `void`
- **Description:** Stops the scan loop and clears detected targets.
- **Parameters:** None
- **Flow:**
1. Clear scan timer
2. Clear DetectedTargets array
3. Set DetectionState = NoTarget
4. Fire OnTargetLost
5. Clear any highlight effects
#### `PerformInteraction` → `S_InteractionResult`
- **Description:** Executes interaction on the current best target.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `InputMode` | `E_InteractionInputMode` | How the input was triggered |
- **Flow:**
1. If not CurrentTarget valid or CurrentTarget actor is None: return failure
2. If bIsPerformingInteraction: return failure (already interacting)
3. If InputMode != CurrentTarget.InputMode: return failure (input mismatch)
4. Set bIsPerformingInteraction = true
5. Set DetectionState = Interacting
6. Fire OnInteractionStarted
7. Call CurrentTarget.InterfaceRef.ExecuteInteraction (owner)
8. Wait for I_Interactable.OnInteractionCompleted or timeout
9. On completion: set bIsPerformingInteraction = false
10. Resume scanning
11. Return S_InteractionResult with success/failure
#### `CancelInteraction` → `void`
- **Description:** Aborts the current interaction if possible.
- **Parameters:** None
- **Flow:**
1. If not bIsPerformingInteraction: return
2. Call CurrentTarget.InterfaceRef.CancelInteraction
3. Set bIsPerformingInteraction = false
4. HoldInteractionProgress = 0.0
5. Set DetectionState = TargetConfirmed
6. Fire OnInteractionCancelled
#### `GetBestTarget` → `S_InteractableTarget`
- **Description:** Returns the current best target.
- **Parameters:** None
- **Flow:** Return CurrentTarget
#### `HasTarget` → `Boolean`
- **Parameters:** None
- **Flow:** Return DetectionState >= TargetInRange
#### `ForceSetTarget` → `void`
- **Description:** Forcefully sets a specific target (for scripted interactions).
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `TargetActor` | `AActor` | The specific actor to target |
- **Flow:**
1. If TargetActor implements I_Interactable:
- Build S_InteractableTarget
- Set CurrentTarget
- Set DetectionState = TargetConfirmed
- Fire OnTargetFound
2. Else: fire OnInteractionError(not interactable)
### Private Functions
#### `ScanForInteractables (Timer)` → `void`
- **Description:** Timer callback — performs trace and sorts targets.
- **Flow:**
1. If DetectionState == Interacting: return (skip scan while interacting)
2. Get camera forward vector and world location
3. Sphere trace forward (TraceRadius, InteractionRange, TraceChannel)
4. For each hit actor:
- If implements I_Interactable: add to DetectedTargets
- If not: skip
5. Remove duplicates by actor reference
6. Sort by Priority (descending), then Distance (ascending)
7. Clamp to MaxTargetsInRange
8. Track enter/exit for each actor — fire OnTargetEntered / OnTargetExited
9. Select BestTarget from sorted list
10. Update DetectionState accordingly
11. Fire OnTargetFound or OnTargetLost
#### `CalculateInteractionScore` → `Float`
- **Description:** Computes a score for a target based on priority, distance, and facing angle.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `Target` | `S_InteractableTarget` | The target to score |
- **Flow:**
1. Score = Priority * 100 - Distance * 0.5
2. Facing bonus: if angle < 15 deg, add 50
3. Return Max(0, Score)
#### `HighlightTarget` → `void`
- **Description:** Applies highlight effect to target actor.
- **Parameters:**
| Param | Type | Description |
|-------|------|-------------|
| `Target` | `S_InteractableTarget` | Target to highlight |
| `bHighlighted` | `Boolean` | Whether to enable or disable |
- **Flow:**
1. Call Target.InterfaceRef.SetHighlighted(bHighlighted)
#### `GetViewTraceOrigin` → `Vector, Vector`
- **Description:** Returns camera location and forward direction for trace.
- **Parameters:** None
- **Flow:**
1. If OwnerCameraManager valid:
- Return cam location and forward vector
2. Else: fall back to owner actor location and forward
---
## 5. Event Dispatchers
| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnTargetFound` | `S_InteractableTarget NewTarget` | `Public` | New best target selected |
| `OnTargetLost` | `S_InteractableTarget LostTarget` | `Public` | Current target lost from view / range |
| `OnTargetEntered` | `AActor TargetActor` | `Public` | Actor entered detectable range |
| `OnTargetExited` | `AActor TargetActor` | `Public` | Actor left detectable range |
| `OnInteractionStarted` | `S_InteractableTarget Target` | `Public` | Interaction began |
| `OnInteractionCompleted` | `S_InteractionResult Result` | `Public` | Interaction finished |
| `OnInteractionCancelled` | `S_InteractableTarget Target` | `Public` | Interaction was cancelled |
| `OnInteractionError` | `FText ErrorMessage` | `Public` | Interaction blocked or failed |
| `OnHoldProgressUpdated` | `Float Progress`, `S_InteractableTarget Target` | `Public` | Hold interaction progress [0..1] |
---
## 6. Overridden Events / Custom Events
### Event: `BeginPlay`
- **Description:** Cache references, bind to relevant systems, start detection.
- **Flow:**
1. Get owning actor ensure it is a Pawn
2. Get Player Controller from owner
3. Get Player Camera Manager from controller
4. Bind to BPC_MovementStateSystem.OnPostureChanged block when hidden
5. Bind to BPC_HealthSystem.OnDeathStateChanged block when dead
6. StartDetection()
### Custom Event: `OnInputInteractPressed`
- **Description:** Handles press input for interaction.
- **Flow:**
1. If DetectionState < TargetConfirmed: return
2. If CurrentTarget.InputMode == Press:
- PerformInteraction(Press)
3. If CurrentTarget.InputMode == Hold:
- Start hold timer
4. If CurrentTarget.InputMode == DoubleTap:
- Wait for second press within threshold
### Custom Event: `OnHoldProgressTick (Timer)` → `void`
- **Description:** Ticks hold interaction progress and fires progress dispatcher.
- **Flow:**
1. HoldInteractionProgress += DeltaTime / CurrentTarget.HoldDuration
2. Clamp to 1.0
3. Fire OnHoldProgressUpdated
4. If HoldInteractionProgress >= 1.0: PerformInteraction(Hold)
### Custom Event: `OnInputInteractReleased`
- **Description:** Cancels hold interaction if button released early.
- **Flow:**
1. If CurrentTarget.InputMode == Hold and not completed:
- CancelInteraction()
- HoldInteractionProgress = 0.0
---
## 7. Blueprint Graph Logic Flow
```mermaid
flowchart TD
A[Scan Timer Fires] --> B[Get Camera Location / Forward]
B --> C[SphereTraceForObjects]
C --> D[Hit actors found?]
D -->|No| E[Clear targets]
E --> F[DetectionState = NoTarget]
F --> G[Fire OnTargetLost]
D -->|Yes| H[Filter by I_Interactable]
H --> I[Sort by Priority then Distance]
I --> J[Select BestTarget]
J --> K{BestTarget changed?}
K -->|Yes| L[Unhighlight old target]
L --> M[Highlight new target]
M --> N[Fire OnTargetFound]
K -->|No| O[Keep current target]
P[OnInputInteractPressed] --> Q{DetectionState >= Confirmed?}
Q -->|No| R[Return]
Q -->|Yes| S{InputMode match?}
S -->|Press| T[PerformInteraction]
S -->|Hold| U[Start hold timer]
S -->|DoubleTap| V[Start double-tap timer]
T --> W[Call ExecuteInteraction on target]
W --> X[Fire OnInteractionStarted]
X --> Y{Interaction succeeded?}
Y -->|Yes| Z[Fire OnInteractionCompleted]
Y -->|No| AA[Fire OnInteractionError]
```
---
## 8. Communication Matrix
| Who Talks | How | What Is Sent |
|-----------|-----|-------------|
| `BPC_InteractionDetector` | `Dispatcher` | `OnTargetFound` -> `WBP_InteractionPrompt` (show prompt) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnTargetLost` -> `WBP_InteractionPrompt` (hide prompt) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnInteractionStarted` -> `BPC_PlayerMetricsTracker` (log event) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnInteractionCompleted` -> `BPC_PlayerMetricsTracker` (log result) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnHoldProgressUpdated` -> `WBP_InteractionPrompt` (progress bar) |
| `BPC_InteractionDetector` | `Dispatcher` | `OnInteractionCancelled` -> `WBP_InteractionPrompt` (hide) |
| `BPC_InteractionDetector` | `Listener` | Binds to `BPC_MovementStateSystem.OnPostureChanged` |
| `BPC_InteractionDetector` | `Listener` | Binds to `BPC_HealthSystem.OnDeathStateChanged` |
| `BPC_InteractionDetector` | `Direct` | Calls `I_Interactable.ExecuteInteraction` on target |
| `BPC_InteractionDetector` | `Direct` | Calls `I_Interactable.CancelInteraction` on target |
| `BPC_InteractionDetector` | `Direct` | Calls `I_Interactable.SetHighlighted` on target |
| `BPC_InteractionDetector` | `Direct call (other)` | `GetBestTarget` called by `WBP_InteractionPrompt` for name |
| `PC_PlayerController` | `Input Event` | Binds press / release / hold to `OnInputInteractPressed` etc. |
---
## 9. Validation / Testing Checklist
- [ ] Trace detects actors implementing I_Interactable at correct range
- [ ] Priority sorting: Emergency targets always selected over Low
- [ ] Same priority: closest target selected
- [ ] Detection respects blocking states (dead, hiding)
- [ ] Hold interaction progress updates and fires progress dispatcher
- [ ] Double-tap interaction waits for second press within window
- [ ] Cancelling hold interaction resets progress and fires cancelled
- [ ] Interaction blocked during combat if bBlockDuringCombat is true
- [ ] Targeting auto-switches if closer target enters range
- [ ] Target exit detection fires when actor moves beyond max range
- [ ] Edge case: No targets in range — DetectionState stays NoTarget
- [ ] Edge case: Target destroyed mid-interaction — cancels gracefully
- [ ] Edge case: Multiple interactables in trace — selects correctly
- [ ] Debug trace visualisation draws correct sphere/line
- [ ] Scan timer pauses while interacting, resumes after completion
---
## 10. Reuse Notes
- TraceChannel should be set to a custom object channel (ECC_GameTraceChannel1) with only interactable actors responding.
- Priority values can be overridden per actor via the `I_Interactable` interface's `GetInteractionPriority` function.
- The hold interaction progress is designed to drive a radial progress widget in the HUD.
- For controller/console: `E_InteractionInputMode.Hold` is preferred to prevent accidental interactions.
- The same component can be attached to NPCs if they need interaction detection.
- To support networked games: replicate CurrentTarget and have each client run their own trace locally.
---
*Blueprint Spec: Interaction Detector. Conforms to TEMPLATE.md v1.0 — part of the UE5 Modular Game Framework.*