5.1.Grip Motion Controller
2021- Hand Smoothing Added
Hand smoothing
If bSmoothHandTracking is enabled the motion controllers will now automatically smooth themselves to remove jitter. Either with a naive lerp or a 1Euro Low Pass filter (suggested).
05/25/18 Gripping an actor now auto sets the actors owner as the grip controllers owner. This is to allow for some bug fixes and utility. You can reset owner to null on release if you want.
Notes
- This component uses direct movement of objects to handle gripping instead of attachment (unless using the attachment grip type).
How do I use it?
- Replace your current MotionControllerComponents with GripMotionControllerComponents
- When you wish to pick up an object call the components “GripObject” function, it will return “true/false” if the grip was successful. (See below for breakdowns of functions)
- When you wish to drop an object call the “DropObject” function, it will return true/false if the drop was successful, false means it could not find that object as gripped. (See below for breakdowns of functions)
- All actors to be gripped currently MUST have a UPrimitiveComponent derived component as the ROOT component (otherwise it will return false as it doesn’t know what to grip or simulate). The root component also is REQUIRED to be movable. If gripping a Child component instead, it must also be attached to an actor set to movable.
- When teleporting a character you have to call “PostTeleportMoveGrippedActors” on each GripMotionControllerComponent. This moves all gripped actors to the new location WITHOUT allowing for collision with obstacles in the way and without updating the physics velocity. If you do not do this then the gripped actors will follow WITH collision and may get stuck on obstacles on the way.
For the VRCharacter this is not required as it is done for you.
GripControllerComponent Bindable Delegates
OnGrippedObject – Called when an object has been gripped – utility delegate Called on all connections
OnDroppedObject – Called when an object has been dropped – utility delegate Called on all connections
OnControllerProfileTransformChanged – Called when the current controller profile transform has changed, primarily used to adjust procedural meshes to match the new transform.
OnGripOutOfRange – Called when a grip goes out of its interactible range. If this is not bound then the grip logic will auto drop the object, if this IS bound, then the delegate gets called instead. Called on all connections
GripControllerComponent Variables
bool bUseWithoutTracking – If set gripped actors will still follow the controller even if there is no tracking for the hand it is assigned to. This is mainly used for testing grip functionality without a headset on or VR equipment set up at the time. A first or third person pawn can use it with this set and it parented to the camera and still test gripping and dropping.
AdditionalLateUpdateComponents – An array of components that you want to force to follow late updates for this motion controller. Can be added / removed to/from in blueprint. Useful for things that you aren’t actually holding and aren’t attached to the controllers but that you want to get the late update.
bool bOffsetByHMD – Offsets the controller back by the HMDs relative location, this is used with the SimpleCharacter as the HMD is set to x0,y0 in that character and the controllers relative location would otherwise be incorrect. Now exposed to blueprint In case someone needs it for custom logic or a custom character.
Grip Collision Styles
- InteractiveCollisionWithPhysics – Collides with the enviroment and will offset from the hand and not pass through objects, uses physics only.
- InteractiveCollisionWithSweep – Collides with the enviroment and will offset from the hand and not pass through objects, does not use physics for collision, will still interact with simulating objects.
- InteractiveHybridCollisionWithPhysics (WIP) – Same as InteractiveCollisionWithPhysics, except when not in collision the physics constraint stiffness is multiplied by 10 to better match the hand. When in collision it is softened again to the passed in settings so that it won’t jitter or be too springy on colliding surfaces.
- InteractiveHybridCollisionWithSweep (incomplete) – Locks to hand during normal use, switches to physics based when it makes contact with a blocking actor.
- SweepWithPhysics – Uses non colliding sweeps to move the gripped actor, will pass through the environment but will still trigger OnHit events and interact with simulating objects.
- PhysicsOnly – Uses non colliding move commands to position the gripped actor, will pass through the environment but will still interact with simulating objects. Will NOT trigger OnHit events (essentially the same as AttachTo).
- AttachmentGrip * – Attachs the object to the controller, doesn’t set the location on tick unless it doesn’t match the transform it is supposed to be at (secondary grips, ect).
- ManipulationGrip – Uses a point of contact rotationally loose constraint to grip the object, this will provide good use cases for doors/drawers/knobs/levers/dials ect that use physics to function.
- ManipulationGripWithWristTwist – Uses a point of contact rotationally loose constraint to grip the object, this will provide good use cases for doors/drawers/knobs/levers/dials ect that use physics to function. This one also has Wrist twisting motion enabled.
Grip Replication Styles
enum class EGripMovementReplicationSettings : uint8
Server must call grip for these
- KeepOriginalMovement – Keeps whatever replication setting the object already had (Not local compatible)
- ForceServerSideMovement – Forces server sided movement, objects likely need their own movement replication setup as the engine default is not lerped and is pretty terrible.
- ForceClientSideMovement – Turns off movement replication while gripped, each client grips and moves the object to follow the controller. Server has authority on grip and replicates the settings and grip state.
Each client must call grip for this
- Client Authority Client has total authority over this grip, they call Grip/Drop functions and the calls are automatically replicated to the server.
- Client Authority_Not_Replicated – Pure local/client side gripping, can be used for objects that other players don’t need to see or objects that other players will never directly interact with. IE: Guns that no other player can pick up can use this mode. This way the client will see no delay between attempting to pick up the object and picking it up. You would replicate the grip command to the server, and have it multicast back to all non owning clients to locally grip it as well. For this grip, any grip replication that you want must be manually handled by you.
Best Practices
- If only picking up one actor at a time per hand, store them in a BP variable, then when going to pick up a new actor you can cancel if it is already held by that hand or make the other hand drop the actor if it is holding it (calling DropObject on it just to be safe is valid, you do not need to check in blueprint necessarily, but for this case I would have bSimulate turned off).
- Use a sphere trace to check for an object from the controller to pickup, with the right radius you can match the diameter of the controller / hand and it has less problems than overlaps for quick movements. Use Persistent drawing on the trace until it looks right and matches where you want the grip location to be. Have it fallback to an overlap on fail to get subcases like when the controller is inside of the object.
- Either remove collision from subcomponents to the controller or set “IgnoreMoveActor” on the pawn for a short period when dropping/throwing an item that may collide with the hand on the way out, otherwise the item may be thrown off course. Generally this applies mostly if the momentum is inward towards the hand itself and not outward away from it.
- Only pass in mobile actors to the grip function. Setting mobility on an object during runtime is considered unsafe so the controller no longer does it.
- Pre-filter in BP the actor types that are allowed to be picked up, the function does not care what you pass to it and will even attempt to pick up terrain actors.
- Set some sort of breaking distance where if a gripped actor is too far away that it will get dropped. This can be managed with interaction settings.
Blueprint Function Explanations
GripObject
- ObjectToGrip – The object that you want picked up
- WorldOffset – The transform that you want the picked up object to stick to, this is in worldspace and automatically creates the relative offset from the gripping component.
- WorldOffsetIsRelative – If true then the worldoffset will be treated as relative already and will not be converted from world space. Can be used for snapping functionality by passing in a Sockets RelativeTransform (actor or component space) or to null out offsets at all by passing in an empty transform. (Transforms with positions of worldspace 0,0,0 would not be 0,0,0 relative to an object without this set to true).
- OptionalSnapToSocketName – An optional input that if set to a valid socket name will override the WorldOffset and instead snap the object to the controller using the relative offset of the named socket. Socket must be on the root component if picking up an actor for this to work, it does not currently iterate child components to look for the socket.
- GripCollisionType – Type of collision to use for the gripped actor
- GripStiffness – Stiffness of the physx link when holding simulating actors
- GripDamping – Damping on the movement of held simulating actors
- LateUpdateSetting – Different available late update settings for the gripped object.
Returns true/false whether the object was gripped or not.
The default use of this would be to pass in the GetComponent/ActorTransform to the WorldOffset. The function would then get the relative position of the object from the controller and lock the object to it until dropped.
If you wanted snap functionality you would:
- Create a mesh socket for the root component of the actor or the component to grip
- Name the socket in the grip function
- If the socket is not on the root component of an actor when gripping an actor then pass its component or actor space transform in as WorldOffset and set WorldOffsetIsRelative to true.
You can of course mix the two versions by using snap if the grab is within a distance of a snap point.
DropObject
- ObjectToDrop – The Object that you are attempting to drop, if it is not currently held it will just return false
- bSimulate – Whether to set the gripped Object to simulate after dropping, if false the object will be frozen in place instead.
- OptionalLinearVelocity – An optional node that if filled with a linear velocity will apply it to the dropped actor/component on the server side after it has been dropped. This is so that client side latency doesn’t get in the way of throwing.
- OptionalAngularVelocity – An optional node that if filled with a linear velocity will apply it to the dropped actor/component on the server side after it has been dropped. This is so that client side latency doesn’t get in the way of throwing.
Returns true/false whether the object was found and dropped.
AddSecondaryAttachmentPoint
Used to create a secondary grip on a held actor.
- GrippedActorToAddAttachment – Actor that is currently held by this controller that you want to add a secondary attachment to.
- SecondaryPointComponent – Component to have as the secondary grip point
- Original Transform – Transform to use, either pass in a sockets relative transform on the base actor or the secondary point components relative transform to the base actor. Can use ConvertToGripRelativeTransform() node to do this for you.
- bTurnOffLateUpdates – Whether to stop late updates when dual gripping, defaults to true, if using something like a gun this will prevent aim jitter.
- LerpToTime – Time in seconds to lerp the gripped actor over to the new position
- SecondarySmoothingScaler – Scaler 0.1 – 1.0 of how much influence the secondary attachment has from one frame to another (0.1 would add almost a 1 frame delay to movements).
RemoveSecondaryAttachmentPoint
Removes a secondary grip component from a grip.
- GrippedActorToRemoveAttachment – Actor that is currently held by this controller that you want to remove the secondary attachment from.
- LerpToTime – Time in seconds to lerp the two handed position back to the single handed position.