Add haptics example documentation for Project Void controller feedback

- Introduced comprehensive guide for setting up controller haptics and force feedback.
- Detailed directory structure for haptic profiles and creation steps for DA_HapticProfile instances.
- Included platform-specific configurations for Xbox and PS5 DualSense adaptive triggers.
- Outlined wiring of BPC_HapticsController to various gameplay systems and events.
- Provided accessibility integration options and testing checklist for haptic functionality.
This commit is contained in:
Lefteris Notas
2026-05-22 17:16:34 +03:00
parent 7c2e8df6b1
commit 14441c000c
16 changed files with 1213 additions and 46 deletions

View File

@@ -51,7 +51,7 @@ The Modular Game Framework uses `UDataAsset` (and subclass `UPrimaryDataAsset` w
| 11 | `DA_ScareEvent` | Adaptive | `BPC_ScareEventSystem` |
| 12 | `DA_RoomMutation` | Adaptive | `BPC_AdaptiveEnvironmentDirector` |
| 13 | `DA_BehaviourVariant` | AI | `BPC_BehaviourVariantSelector` |
| 14 | `DA_HapticProfile` | Settings | `BPC_HapticsController` |
| 14 | `DA_HapticProfile` | Settings | `BPC_HapticsController` (148) |
| 15 | `DA_AdaptationRule` | Adaptive | `BPC_DifficultyManager` |
| 16 | `DA_EquipmentConfig` | Inventory | `BPC_EquipmentSlotSystem` |
| 17 | `DA_PuzzleData` | Interaction | `BP_PuzzleDeviceActor` |

View File

@@ -1,52 +1,178 @@
# DA_HapticProfile — Data Asset
**Parent Class:** `UDataAsset`
**Dependencies:** [`BPC_HapticsController`](../12-settings/)
**Purpose:** Defines haptic feedback profiles for controller vibration and force feedback effects tied to gameplay events.
**Parent Class:** `UPrimaryDataAsset`
**Dependencies:** [`BPC_HapticsController`](../12-settings/148_BPC_HapticsController.md)
**Purpose:** Defines haptic feedback profiles for controller vibration and force feedback effects tied to gameplay events. Each profile maps a GameplayTag to a platform-specific `UForceFeedbackEffect` waveform asset with configurable intensity, duration, motor mask, and priority.
---
## Enums Used
| Enum | Defined In | Values |
|------|-----------|--------|
| `EHapticEvent` | `BPC_HapticsController` (148) | Damage, HeavyDamage, Heartbeat, WeaponFire, WeaponReload, MeleeImpact, Footstep, Explosion, PickupItem, DropItem, GrabObject, ReleaseObject, ScareEvent, AmbientPulse, UI_Confirm, UI_Navigate, LowHealth, StaminaExhausted, Death |
| `EHapticMotor` | `BPC_HapticsController` (148) | Left, Right, Both |
---
## Variables / Structure
### Core Fields
| Field | Type | Description |
|-------|------|-------------|
| `ProfileTag` | `FGameplayTag` | Unique haptic profile identifier |
| `EventType` | `EHapticEvent` | Damage, Heartbeat, Explosion, Footstep, WeaponFire, AmbientPulse |
| `IntensityCurve` | `UCurveFloat*` | Vibration intensity over time |
| `Duration` | `float` | Total haptic effect duration (seconds) |
| `MotorMask` | `EHapticMotor` | Left, Right, Both |
| `Priority` | `int32` | Higher priority overrides lower during conflicts |
| `bCanInterrupt` | `bool` | Can this effect be interrupted by higher priority |
| `PlatformMinIntensity` | `float` | Minimum intensity per platform capability |
| `ProfileTag` | `FGameplayTag` | Unique haptic profile identifier (e.g., `Haptic.Damage.Heavy`) |
| `EventType` | `EHapticEvent` | Event category this profile handles |
| `ForceFeedbackEffect_Generic` | `UForceFeedbackEffect*` | Waveform curve asset for PC/Xbox generic controllers |
| `ForceFeedbackEffect_PS5` | `UForceFeedbackEffect*` | Waveform curve asset for PS5 DualSense (higher fidelity) |
| `ForceFeedbackEffect_Xbox` | `UForceFeedbackEffect*` | Waveform curve asset for Xbox controllers (optional override) |
| `IntensityCurve` | `UCurveFloat*` | Optional: vibration intensity over time (0.01.0) |
| `Duration` | `float` | Total haptic effect duration in seconds |
| `MotorMask` | `EHapticMotor` | Left motor, Right motor, or Both |
| `Priority` | `int32` | Higher priority overrides lower during conflicts (0 = lowest, 100 = highest) |
| `bCanInterrupt` | `bool` | Can this effect be interrupted by a higher-priority effect? |
| `bIgnoreTimeDilation` | `bool` | Should this play at real-time regardless of game speed? |
### Platform-Specific Fields
| Field | Type | Description |
|-------|------|-------------|
| `PlatformMinIntensity` | `float` | Minimum intensity threshold before effect is felt (0.01.0) |
| `DualSense_TriggerSide` | `FName` | PS5 adaptive trigger side ("Left", "Right", "None") |
| `DualSense_TriggerEffect` | `FName` | PS5 trigger effect type ("Resistance", "Vibration", "WeaponFire", "BowDraw", "None") |
| `DualSense_TriggerStartPosition` | `int32` | PS5 trigger position where effect begins (09) |
| `DualSense_TriggerStrength` | `int32` | PS5 trigger effect strength (08) |
### Heartbeat-Specific Fields
| Field | Type | Description |
|-------|------|-------------|
| `bIsHeartbeatProfile` | `bool` | Whether this profile is used for heartbeat pulse effects |
| `TargetBPMRange_Min` | `float` | Minimum BPM this profile handles |
| `TargetBPMRange_Max` | `float` | Maximum BPM this profile handles |
---
## Gameplay Tags
- Namespace: `Haptic.<Event>` (e.g., `Haptic.Damage.Heavy`, `Haptic.Heartbeat`)
- Namespace: `Haptic.<Category>.<Subcategory>`
- Examples: `Haptic.Damage.Heavy`, `Haptic.Heartbeat.Normal`, `Haptic.WeaponFire.Pistol`
- All tags must be registered in `DT_Tags_Player.csv` for validation at startup
### Full Tag Hierarchy
```
Haptic.
├── Damage.Light
├── Damage.Heavy
├── Damage.Critical
├── Heartbeat.Normal
├── Heartbeat.Fast
├── Heartbeat.Panic
├── WeaponFire.Pistol
├── WeaponFire.Shotgun
├── WeaponReload
├── MeleeImpact.Crowbar
├── MeleeImpact.Default
├── Footstep.Tile
├── Footstep.Wood
├── Footstep.Concrete
├── Footstep.Metal
├── Footstep.Gravel
├── Explosion
├── Pickup.Item
├── Pickup.Weapon
├── Grab
├── Release.Throw
├── Scare.JumpScare
├── Scare.TensionRise
├── Ambient.Void
├── Ambient.Default
├── LowHealth
├── StaminaExhausted
├── Death
├── UI.Confirm
└── UI.Navigate
```
---
## Validation Rules
- `ProfileTag` must be unique
- `Duration` must be > 0
- `IntensityCurve` must be valid
- `ProfileTag` must be unique across all profiles
- `Duration` must be > 0.0
- At least one `ForceFeedbackEffect_*` must be assigned (Generic falls back for all platforms)
- `Priority` must be 0100
- If `bIsHeartbeatProfile` is true, `TargetBPMRange_Min` and `TargetBPMRange_Max` must be set
- If `DualSense_TriggerSide != "None"`, trigger effect fields must be valid
---
## Example Data
### Damage Profile — Heavy Hit
| Field | Value |
|-------|-------|
| ProfileTag | `Haptic.Damage.Critical` |
| EventType | Damage |
| Duration | 0.5 |
| MotorMask | Both |
| Priority | 10 |
| `ProfileTag` | `Haptic.Damage.Heavy` |
| `EventType` | `HeavyDamage` |
| `Duration` | `0.4` |
| `MotorMask` | `Both` |
| `Priority` | `80` |
| `bCanInterrupt` | `true` |
| `bIgnoreTimeDilation` | `true` |
| `ForceFeedbackEffect_Generic` | `FFE_Damage_Heavy` |
| `ForceFeedbackEffect_PS5` | `FFE_Damage_Heavy_PS5` |
### Heartbeat Profile — Normal
| Field | Value |
|-------|-------|
| `ProfileTag` | `Haptic.Heartbeat.Normal` |
| `EventType` | `Heartbeat` |
| `Duration` | `0.1` |
| `MotorMask` | `Left` |
| `Priority` | `30` |
| `bCanInterrupt` | `true` |
| `bIsHeartbeatProfile` | `true` |
| `TargetBPMRange_Min` | `60.0` |
| `TargetBPMRange_Max` | `90.0` |
| `ForceFeedbackEffect_Generic` | `FFE_Heartbeat` |
### Weapon Fire — Pistol
| Field | Value |
|-------|-------|
| `ProfileTag` | `Haptic.WeaponFire.Pistol` |
| `EventType` | `WeaponFire` |
| `Duration` | `0.08` |
| `MotorMask` | `Right` |
| `Priority` | `50` |
| `DualSense_TriggerSide` | `Right` |
| `DualSense_TriggerEffect` | `WeaponFire` |
| `DualSense_TriggerStartPosition` | `4` |
| `DualSense_TriggerStrength` | `6` |
---
## Consumed By
- [`BPC_HapticsController`](../12-settings/)
- [`BPC_HapticsController`](../12-settings/148_BPC_HapticsController.md) — loads all profiles into `HapticProfileMap` at initialization
## Referenced By
- `BPC_HealthSystem` (08) — damage haptics
- `BPC_FirearmSystem` (74) — weapon fire haptics
- `BPC_MeleeSystem` (76) — melee impact haptics
- `BPC_ScareEventSystem` (101) — scare event haptics
- `BPC_MovementStateSystem` (11) — footstep haptics
- `BPC_ReloadSystem` (78) — reload haptics
- `BPC_PhysicsDragSystem` (22) — grab/release haptics
- `BP_ItemPickup` (25) — pickup haptics
- `BPC_DeathHandlingSystem` (39) — death haptics
- `BPC_StaminaSystem` (09) — stamina exhausted haptics
---
## Reuse Notes
- Haptic profiles are platform-agnostic; translation handled by PlatformServiceAbstraction
- Haptic profiles are platform-agnostic in design; `BPC_HapticsController` selects the correct `UForceFeedbackEffect` asset at runtime based on `CurrentPlatform`.
- Designers create FFE waveform curves in the Content Browser — no Blueprint changes needed for tuning.
- For heartbeat profiles: create 3 instances (Normal 60-90 BPM, Fast 90-140 BPM, Panic 140-180 BPM). `BPC_HapticsController` auto-selects based on current BPM.
- For footstep profiles: create one per surface type. `BPC_MovementStateSystem` selects based on physical surface trace result.
- Priority guidelines: 020 (ambient/footsteps), 3050 (weapons/reload/pickups), 6080 (damage), 90100 (scares/death).
- The `Haptic.` namespace should be registered in `DT_Tags_Player.csv` so `DA_GameTagRegistry` validates them at startup.

View File

@@ -5,7 +5,7 @@ Primary Data Asset that defines all Enhanced Input bindings across three platfor
## Dependencies
- **Requires:** None (self-contained Data Asset)
- **Required By:** [`SS_EnhancedInputManager`](docs/blueprints/15-input/128_SS_EnhancedInputManager.md) (loads and caches this), [`SS_SettingsSystem`](docs/blueprints/12-settings/105_SS_SettingsSystem.md) (references for key rebinding)
- **Required By:** [`SS_EnhancedInputManager`](docs/blueprints/15-input/128_SS_EnhancedInputManager.md) (loads and caches this), [`SS_SettingsSystem`](docs/blueprints/12-settings/105_SS_SettingsSystem.md) (references for key rebinding), [`BPC_HapticsController`](docs/blueprints/12-settings/148_BPC_HapticsController.md) (reads `bEnableControllerRumble` for haptics master toggle)
- **Engine/Plugin Requirements:** Enhanced Input Plugin, `UInputMappingContext`, `UInputAction`
## Class Info
@@ -68,7 +68,7 @@ Primary Data Asset that defines all Enhanced Input bindings across three platfor
| `PlatformProfiles` | `TArray<S_PlatformProfile>` | `Empty` | `Profiles` | One profile per platform (3 total) |
| `ContextDefinitions` | `TArray<S_ContextDefinition>` | `Empty` | `Contexts` | IMC asset references and defaults |
| `GlobalDeadZone` | `Float` | `0.15` | `Global` | Fallback analog stick dead zone |
| `bEnableControllerRumble` | `Bool` | `true` | `Global` | Master toggle for force feedback |
| `bEnableControllerRumble` | `Bool` | `true` | `Global` | Master toggle for force feedback (read by BPC_HapticsController) |
| `bSwapSticksForLeftHanded` | `Bool` | `false` | `Accessibility` | Swap left/right stick for accessibility |
| `AxisInvertSettings` | `TMap<FName, Bool>` | `Empty` | `Accessibility` | Per-action axis inversion (e.g., "IA_Look" = InvertY) |