# BPC_PhysicsDragSystem — Physics Drag System **Parent Class:** `ActorComponent` **Category:** Interaction **Target UE Version:** 5.5–5.7 **Build Phase:** 2 — Interaction --- ## 1. Overview `BPC_PhysicsDragSystem` allows the player to grab and physically drag rigid-body objects in the world. Supports grab-at-distance, hold-to-grab with physics constraints, object rotation, and throw mechanics. Integrates with the interaction detector for grab targeting. --- ## 2. Enums ### `E_DragMode` | Value | Description | |-------|-------------| | `PhysicsConstraint` | Attaches object via physics constraint to player hand | | `Kinematic` | Sets object to kinematic and parents to hand | | `Magnetic` | Objects smoothly lerp toward grab point | --- ## 3. Variables | Name | Type | Description | |------|------|-------------| | `DragMode` | `E_DragMode` | Current drag physics mode | | `GrabbedObject` | `AActor*` | Currently held actor | | `ConstraintComp` | `UPhysicsConstraintComponent*` | Physics constraint for held object | | `GrabDistance` | `float` | Max distance to grab (cm) | | `HoldDistance` | `float` | Distance object is held from camera | | `ThrowForce` | `float` | Impulse applied on release | | `RotationSpeed` | `float` | Degrees/sec for object rotation input | | `bCanThrow` | `bool` | Object can be thrown on release | | `bIsGrabbing` | `bool` | Currently holding an object | --- ## 4. Functions | Function | Description | |----------|-------------| | `GrabObject` | Attempts to grab targeted physics object. Returns bool. | | `ReleaseObject` | Releases held object, applies throw force if bCanThrow. | | `RotateObject` | Rotates held object by input axis values | | `SetHoldDistance` | Adjusts distance of held object from camera | | `GetGrabbedObject` | Returns currently held actor (or null) | | `IsGrabbing` | Returns `bIsGrabbing` | --- ## 5. Event Dispatchers | Dispatcher | Payload | Description | |------------|---------|-------------| | `OnObjectGrabbed` | `AActor* GrabbedObject` | Object successfully grabbed | | `OnObjectReleased` | `AActor* ReleasedObject`, `bool bWasThrown` | Object released | | `OnGrabFailed` | `FText FailReason` | Grab attempt failed | --- ## 6. Blueprint Flow ``` GrabObject: → Get targeted object from InteractionDetector → Check if object has physics simulation enabled → If DragMode == PhysicsConstraint: → Create physics constraint between hand socket and object → Set constraint limits (linear + angular) → If DragMode == Kinematic: → Set object simulated physics to false → Attach to hand socket → Set bIsGrabbing = true → Broadcast OnObjectGrabbed ReleaseObject: → If bCanThrow → Apply forward impulse * ThrowForce → Destroy constraint / detach → Re-enable physics on object → Set bIsGrabbing = false → Broadcast OnObjectReleased ``` --- ## 7. Dependencies & Communication | System | Relationship | |--------|--------------| | `BPC_InteractionDetector` | Provides grab target via focus | | `BPC_CameraStateLayer` | Camera direction for throw vector | | `BPC_MovementStateSystem` | Speed modifier while carrying objects | --- ## 8. Reuse Notes - Physics drag uses UE5 physics constraint system for realistic object handling - Objects must have `Simulate Physics = true` and `Mass` configured --- ## 9. Manual Implementation Guide ### 9.1 Class Setup 1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_PhysicsDragSystem` 2. Save to: `Content/Framework/Interaction/` 3. Add to your Player Character. ### 9.2 Variable Initialization (BeginPlay) ``` Event BeginPlay ├─ Set bIsGrabbing = false ├─ Set GrabbedObject = None ├─ Get Owner → Get Component by Class (BPC_InteractionDetector) → Store reference └─ Get Owner → Get PlayerCameraManager → Store for throw direction ``` ### 9.3 Function Implementations #### `GrabObject(TargetActor: Actor)` → `Boolean` **Node-by-Node Logic:** ``` [Function: GrabObject] Step 1: Branch on bIsGrabbing → If true, ReleaseObject first Step 2: Branch on IsValid(TargetActor) → If not, return false Step 3: Get TargetActor → Get Component by Class (StaticMeshComponent) └─ Check: Is Simulate Physics Enabled? → If not, Fire OnGrabFailed("No physics"), return false Step 4: Check mass: StaticMeshComponent.GetMass() → If > MaxGrabMass, fail Step 5: Switch on DragMode: Case PhysicsConstraint: - Create Physics Constraint component (spawn dynamically) - ConstraintComp.SetConstrainedComponents(StaticMeshComponent, None, PlayerHandBone) - Set Linear limits: X=Locked, Y=Locked, Z=Locked (or Free for dangling) - Set Angular limits: Free (can rotate), or limited Case Kinematic: - StaticMeshComponent.SetSimulatePhysics(false) - StaticMeshComponent.AttachToComponent(PlayerHandSocket) Case Magnetic: - Store target; handle in Tick with Lerp toward hand position Step 6: Set GrabbedObject = TargetActor Step 7: Set bIsGrabbing = true Step 8: Fire OnObjectGrabbed(TargetActor) Step 9: Return true ``` **Nodes Used:** `IsValid`, `Get Component by Class (StaticMeshComponent)`, `Is Simulate Physics Enabled`, `Get Mass`, `Create Constraint`, `SetConstrainedComponents`, `AttachToComponent`, `Branch` #### `ReleaseObject(bThrow: Boolean)` → `void` ``` [Function: ReleaseObject] Step 1: Branch on bIsGrabbing → If false, return Step 2: Branch on bThrow AND bCanThrow: True: - Get PlayerCameraManager → Get Forward Vector - Multiply forward vector by ThrowForce - GrabbedObject.StaticMeshComponent.AddImpulse(throw vector) - OR: if ConstraintComp exists → BreakConstraint, then AddImpulse False: - Just release without force Step 3: Switch on DragMode: - PhysicsConstraint: Destroy ConstraintComp - Kinematic: DetachFromComponent, SetSimulatePhysics(true) - Magnetic: Clear target reference Step 4: Set GrabbedObject = None Step 5: Set bIsGrabbing = false Step 6: Fire OnObjectReleased(GrabbedObject, bThrow) ``` **Nodes Used:** `Get Forward Vector`, `Multiply (Vector * Float)`, `Add Impulse`, `Break Constraint`, `Destroy Component`, `Detach From Component`, `Set Simulate Physics` #### `RotateObject(YawInput: Float, PitchInput: Float, RollInput: Float)` → `void` ``` [Function: RotateObject] Step 1: Branch on bIsGrabbing → If false, return Step 2: Create Rotator from inputs (use RotationSpeed multiplier) - NewRotation = Make Rotator(PitchInput * RotationSpeed * DeltaTime, YawInput * RotationSpeed * DeltaTime, RollInput * RotationSpeed * DeltaTime) Step 3: Switch on DragMode: - PhysicsConstraint: GrabbedObject.AddLocalRotation(NewRotation) - Kinematic: GrabbedObject.AddRelativeRotation(NewRotation) - Magnetic: Rotate the lerp target ``` #### `SetHoldDistance(NewDistance: Float)` → `void` ``` [Function: SetHoldDistance] Step 1: Clamp NewDistance between MinHoldDistance and MaxHoldDistance Step 2: Set HoldDistance = NewDistance Step 3: If DragMode == PhysicsConstraint: - ConstraintComp.SetLinearPositionTarget(PlayerCamera.ForwardVector * HoldDistance) Step 4: If DragMode == Kinematic: - Set Relative Location (X = HoldDistance, Y = 0, Z = 0) on attached component ``` ### 9.4 Event Dispatcher Bindings | Bind to Dispatcher | Custom Event | Logic | |-------------------|-------------|-------| | Input Action: `IA_Grab` (Pressed) | `OnGrabPressed` | Get InteractionDetector.CurrentTarget → Call GrabObject | | Input Action: `IA_Grab` (Released) | `OnGrabReleased` | Call ReleaseObject(true) | | `BPC_InteractionDetector.OnTargetFound` | `OnGrabTargetFound(Target)` | Highlight grabbable object outline | ### 9.5 Networking | Variable | Replication | |----------|-------------| | `bIsGrabbing` | `Replicated` | | `GrabbedObject` | `Replicated` (Actor reference) | **Server RPC:** `Server_GrabObject(TargetActor)` — server validates range, spawns constraint. Physics is server-authoritative; client predicts locally. ### 9.6 Blueprint Build Checklist - [ ] Create BPC_PhysicsDragSystem component, add to Player Character - [ ] Add all variables: DragMode, GrabbedObject, ConstraintComp, GrabDistance, HoldDistance, ThrowForce, RotationSpeed, bCanThrow, bIsGrabbing - [ ] Implement GrabObject with three drag modes (PhysicsConstraint, Kinematic, Magnetic) - [ ] Implement ReleaseObject with throw mechanic - [ ] Implement RotateObject with input axis mapping - [ ] Implement SetHoldDistance with scroll wheel input - [ ] Bind to IA_Grab input action (pressed/released) - [ ] Add MaxGrabMass config to prevent lifting impossibly heavy objects - [ ] Test: grab crate, rotate, throw — physics should feel natural