top of page

VR Hand

Player’s hands are fully physically based and like in player class there was a huge research on immersion, collision and interaction with objects.

Class name:

Include:

Type:

Lines of code:

AVR_Hand

#include "VR/VR_Player/VR_Hands.h"

Player

5450

​General Information

Description

VR Hand is a hand which is being used by player. Hand is using physics and all interactions are using physics as well. The class uses Physics Constraint Component to achieve physics interactions.



VR Hand is a hand which is being used by player. Hand is using physics and all interactions are using physics as well. The class uses Physics Constraint Component to achieve physics interactions.
VR Hands Demo Example

Main features

  • Physics

  • Finger collision

  • Physics interactions

  • Weapon interactions

  • Equipment interactions

  • Finger IK

  • Hand animations

  • Menu functional

  • Radial inventory support


Components


TeleportCylinder, Arrow, RoomScaleMesh, ArcEndPoint, ArcNiagara - Are used for teleportation.

FakeHandMesh - This is a skeletal hand mesh which does not simulate physics. WidgetInteractionComponent - This component is being used for the interaction with the menu actor or other widgets.

RealHandMesh - This component is attached to the HandSocket which simulates physics.

HandSocket - This is sphere component which simulates physics. It is being used because we attach addition collision objects(FingerCollisions and RealHandCollision). If we attach addition collision objects to the skeletal mesh component, collisions will not make any effect.

FingerCollisions - This is capsule components for each finger.

FingerSceneComponets -This is locations in which finger collisions will be place.

RealHandCollision - This is a static mesh for a hand collision.

FLineTraces - This is an arrow components for finger grab IK.

GrabDirection - This is an arrow component for grabbing.

GrabBox - This is a box component for grabbing. Objects in this box can be grabed.

PickPhysicsConstraint - This is a physics constrained component which is being used for grabbing objects.

CA_Inventory - This is a child actor component which uses VR Hand Inventory class. This component is optional.

MenuWristLoader - This is a widget component which displays the pause menu loading bar.

HandPhysicsConstraint - This is a physics constrained component which connects FakeHandMesh and PhysicsHandSocket. Is turned on when hand is colliding.

HandPhysicsConstraintPD - This is a physics constrained component which connects FakeHandMesh and PhysicsHandSocket. Is turned on when hand is not colliding.

MenuCusrsor - This is a cursor which is displayed on widget while interacting.


Tick Algorithm overview


CheckAimToGrab - This function moves hand closer to the object near hand by using a Physics Constraint Component.   Hand Physics Tick - This function switches between Physics Constraint and PhysicsConstraint Parent Dominate by setting Linear/Angular drive params.  UpdateHandAnimation - This function updates hand animation.  UpdateRoomScaleOutline - This function updates Room-scale outline location relative to Teleport target.  CheckMenuStatus - This function checks for menu and hides physics hand mesh if necessary(unhides fake hand mesh which does not simulate physics). Sets everything up.  UpdateWidgetCursor - This function moves on the menu mesh.  CheckHandsAndControllerDist - This function checks the distance between motion controller and hand mesh. If the distances is over the limit hand will move without a collision response.  CheckControllerAndPickDist - This function checks the distance between motion controller and grabbed object. If the distances is over the limit hand will drop the object.  CheckGrabPoss - This function checks the grab poss of the fingers. If the object is too heavy and distace is over the limit, hand will release the object.  CheckMenuButtonPress - This function checks how long is menu button is pressed.  UpdateAllFingersCollision - This function updates the collision for  each finger.  MakeUpdateWidgetLookAtCamera - This function make loading widget alway face the camera.
VR Hand Tick Algorithm


  • CheckAimToGrab - This function moves hand closer to the object near hand by using a Physics Constraint Component.

  • Hand Physics Tick - This function switches between Physics Constraint and PhysicsConstraint Parent Dominate by setting Linear/Angular drive params.

  • UpdateHandAnimation - This function updates hand animation.

  • UpdateRoomScaleOutline - This function updates Room-scale outline location relative to Teleport target.

  • CheckMenuStatus - This function checks for menu and hides physics hand mesh if necessary(unhides fake hand mesh which does not simulate physics). Sets everything up.

  • UpdateWidgetCursor - This function moves on the menu mesh.

  • CheckHandsAndControllerDist - This function checks the distance between motion controller and hand mesh. If the distances is over the limit hand will move without a collision response.

  • CheckControllerAndPickDist - This function checks the distance between motion controller and grabbed object. If the distances is over the limit hand will drop the object.

  • CheckGrabPoss - This function checks the grab poss of the fingers. If the object is too heavy and distace is over the limit, hand will release the object.

  • CheckMenuButtonPress - This function checks how long is menu button is pressed.

  • UpdateAllFingersCollision - This function updates the collision for each finger.

  • MakeUpdateWidgetLookAtCamera - This function make loading widget alway face the camera.


Physics Constraints

VR hand uses 3 physics constraints: HandPhysicsConstraint, HandPhysicsConstraintPD and PickPhysicsConstraint. HandPhysicsConstraint and HandPhysicsConstraintPD are used for connecting FakeHandMesh and PhysicsHandSocket. In function "HandPhysicsTick" Physics Constraint and PhysicsConstraint Parent Dominate are switching. HandPhysicsConstraint is turned on when hand is colliding and HandPhysicsConstraintPD when hand is not colliding(This is woking by hit events so make sure that every finger collision, handcollision and other objects which developer attached has "Simulation Generate Hit Events" set to true).


HandPhysicsConstraint is turned on when hand is colliding and HandPhysicsConstraintPD when hand is not colliding. This is woking by hit events so make sure that every finger collision, handcollision and other objects which developer attached has "Simulation Generate Hit Events" set to true.
Simulation Generate Hit Events

There are settings in Variables/Physics and Variables/PD (Parent Dominates) categories which are for Physics Constraints. The most important setting is a Drag Curve which effects on constraints depending on the hand and controller distance(Do not forget to set the Drag Curve variable. At least use a default one, otherwise project will crash).


The most important setting is a Drag Curve which effects on constraints depending on the hand and controller distance.
Drag Curve

Hand Skeleton

The default settings are using SteamVR skeleton but it is possible to use Unreal Engine XR skeleton. In the Setting there are Hand section in which you can find the following variables: Reflect Left Hand, Using Steam VR Skeleton and finger bones(This is used in finger collision).


The default settings are using SteamVR skeleton but it is possible to use Unreal Engine XR skeleton. In the Setting there are Hand section in which you can find the following variables: Reflect Left Hand, Using Steam VR Skeleton and finger bones(This is used in finger collision).
Hand Skeleton Settings

Finger Collision(UE 5.2)

Finger collision are using capsule components and FingerSceneComponets(Tip-Start) (SceneComponent). Collision set up requires scene components placment. Each finger tip component (ThumbFingerTip - PinkyFingerTip) should be located at the tip of each finger. Each finger start component (ThumbFingerStart - PinkyFingerStart) should be located at the tip of each finger. Before changing the location of each component developer need to add UpdateAllFingerCollision to the construction script. UpdateAllFingerCollision will place each finger collison between tip and start.


Finger collision are using capsule components and  FingerSceneComponets(Tip-Start) (SceneComponent). Collision set up requires scene components placment. Each finger tip component (ThumbFingerTip - PinkyFingerTip) should be located at the tip of each finger. Each finger start component (ThumbFingerStart - PinkyFingerStart) should be located at the tip of each finger. Before changing the location of each component developer need to add UpdateAllFingerCollision to the construction script. UpdateAllFingerCollision will place each finger collison between tip and start.
Construction Script

Finger Collision(UE 4.27)

Finger collision are using physics blend(works with SteamVR skeleton only). Requires skeletal physics asset set up(See demo skeletal physics asset example).


Hand Animation

FakeHandMesh and RealHandMesh requres hand animation blueprint for the proper usage. Animation Blueprint must be instanced from VR Hand Animation Instance(Animation Blueprint must be set up otherwise project will crash. For the set up see VR Hand Animation instance class).



Line traces for Grab IK

Hand uses 4 line traces(Arrow Componets) for each finger. Each finger rotation value is from 0 to 1 so the value of each line trace is 1/NumberOfTraces(4)=0.25 (Trace 1: 0-0.25, Trace 2: 0.25-0.5, Trace 3: 0.5-0.75 and Trace 3: 0.75-1). The set up requires animation blueprint(For debugin positions) in which IK blend per bone is connected to the output(Picture below). Position of the arrows for the finger should match the finger position in the value range.


Hand uses 4 line traces(Arrow Componets) for each finger. Each finger rotation value is from 0 to 1 so the value of each line trace is 1/NumberOfTraces(4)=0.25 (Trace 1: 0-0.25, Trace 2: 0.25-0.5, Trace 3: 0.5-0.75 and Trace 3: 0.75-1). The set up requires animation blueprint(For debugin positions) in which IK blend per bone is connected to the output(Picture below). Position of the arrows for the finger should match the finger position in the value range.
Animation Blueprint(For debugin positions)

Menu settings

Menu(Actor attached to the FakeHandMesh) can be spawned after holding A button on the left controller(Loading ring will apear while holding the button). Main Menu class and Pause Menu class is classes which will be spawned in certain conditions(Main Menu if Player has true at Menu Status and Pause Menu if player pressed the button). Menu grab animation can be specified.(Do not to forget to select the classes otherwise project will crash)


(Menu loading widget is need to be selected otherwise project will crash)


Hand radial inventory

CA_Inventory(Child Actor Component) is a inventory actor which can be spawned by pressing the thumbstick button on the rightcontroller(Class should be selected at least with 0 values to avoid issues. See VR Hnad Inventory for more information).

Pull Grab

Can Pull Grab - Turns on the pull grab.

Pull Grab Type - Type can be set to Gravity Pull(HL:A Style) or to Direct Pull(Boneworks style). Pull Grab Distance - Maximum pull grab distance.

Pull Check Delay - Delay between pull grab checks.

Other Settings

Ammo Clips - This is an array of classes in which the information of ammo classes is stored. Index is a caliber type which is get from Player(See VR Player). This variable is used in the grabbing function. If hand is in the ammo box and player has some ammo it will spawn the actor of the class from that array by a caliber(Index).

Hit Surface Haptic Effect - This is a Haptic Effect which is playing when hand hit the surface.

Teleport - Variables which effect the teleport.

Grab - Variables which effect the teleport(Speed, Sound etc.).


Blueprint API Reference

Public Member Functions


 

 


virtual void 

OnConstruction (const FTransform &Transform) override

 


virtual void 

BeginPlay () override

 


virtual void 

Tick (float DeltaTime) override

 


virtual void 

EndPlay (EEndPlayReason::Type EndPlayReason) override

 


void 

 


void 

 


void 

 


void 

 


bool 

 


void 

 

If grab button is pressed.

 


void 

 

Release attached Actor.

 


void 

 


void 

 


bool 

TraceTeleportDestination (TArray< FVector > &TracePoints, FVector &NavMeshLocation, FVector &TraceLocation, FRotator &TraceRotation)

 

Traces Teleport Destination , checks if teleport is possible.

 


void 

 

Clears Arc.

 


void 

UpdateArcSpline (bool FoundValidLocation, TArray< FVector > SplinePoints)

 

Updates Arc Spline.

 


void 

UpdateArcEndPoint (bool ValidLocationFound, FVector NewLocation)

 

Updates Arc End Point.

 


void 

GetTeleportDestination (FVector &MyLocation, FRotator &MyRotation)

 

Gets teleport Destination.

 


void 

 

Sets all Fingers IK.

 


void 

ShowTeleportDestenation (bool IsValidTeleportDestination, FVector TraceLocation, FRotator TraceRotation)

 


void 

SetSingleFingerIK (UArrowComponent FingerTrace1, UArrowComponent FingerTrace2, UArrowComponent FingerTrace3, UArrowComponent FingerTrace4, EFinger Finger)

 

Sets Ik for SingleFinger.

 


void 

LineTraceAlongArrow (class UArrowComponent *ArrowToTrace, bool &Hit, float &TraceLength, FHitResult &OutHits)

 

Trace line allong the arrow component.

 


float 

CalculateRatio (float TraceLength, int ArrowNumber)

 

Calculates Rotation.

 


void 

CalculateIKLocations (FVector WorldImpact, FVector &EffectorLocation)

 


void 

ApplyIKToABP (FVector EffectorLocation, float Ratio, EFinger Finger, bool hit)

 

Apply Rotation to Animation blueprint.

 


void 

 

Setup Room Scale Outline.

 


void 

 

Update Room Scale Outline.

 


void 

RumbleController (float Intensity, UHapticFeedbackEffect_Base *HapticEffect)

 

Vibrate the Controller using the Habtics.

 


void 

OnComponentBeginOverlap (class UPrimitiveComponent OverlappedComp, AActor OtherActor, class UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)

 

For Rumble Controller when overlapping valid StaticMesh.

 


void 

 


void 

SetTeleportRotation (FRotator &NewTeleportRotation)

 

Set Teleport Rotation , used in Player_Pawn.

 


void 

 

Checks distance between Controller and Picked object .

 


void 

 

Checks distance between Hands and Controller.

 


void 

 


bool 

TryAimToGrab (FHitResult &Hit, bool ForceInteraction)

 


void 

 

Checks if Teleport is active. Updates Arc Spline , using UpdateArcSpline(bIsValidTeleportDestination, TracePoints) ; Updates Arc end point , using UpdateArcEndPoint(bIsValidTeleportDestination, TraceLocation).

 


virtual void 

 

Trigger Pressed.

 


virtual void 

 

Trigger Touch.

 


virtual void 

 

Grip Pressed.

 


virtual void 

 

Thumb Pressed.

 


virtual void 

 

Trigger Released.

 


virtual void 

 

Trigger UnTouch.

 


virtual void 

 

Grip Released.

 


virtual void 

 

Thumb Released.

 


virtual void 

 

A Pressed.

 


virtual void 

 

A Released.

 


virtual void 

 

B Pressed.

 


virtual void 

 

B Released.

 


virtual void 

 

Sets true if Trackpad being Touched.

 


virtual void 

 


virtual void 

SetIndexPushInst (float inst)

 


virtual void 

SetGripPushInst (float inst)

 


virtual void 

SetTrackpad_Y (float inst)

 


virtual void 

SetAllowAmmo (bool Allow)

 


virtual void 

HandsPickObjHandle (bool Attach)

 


AActor * 

 


void 

SetDontLostConnection (bool DontAllow)

 


void 

SetMainMenuStatus (bool MainMenuStatus)

 

Turns on\off widget component.

 


void 

SetOwnerPawn (AActor *ActorToSet)

 

Sets owner of the MotionController(Player)

 


void 

 


void 

UpdateFingerCollision (UCapsuleComponent Collision, USceneComponent Start, USceneComponent *Tip)

 


void 

 


void 

EnableFingerCollision (bool Enable)

 


bool 

 


void 

 


void 

 


void 

SetCurrentWidgetHand (bool ThisHand)

 

Sets widget on current hand.

 


void 

 

Updates Widget Cursor.

 


void 

 

Check if the grab is possible.

 


void 

CheckPhysBlend (bool force=false)

 


void 

UpdatePhysBlendForFinger (EFinger Finger, FFingerCurls CurrentFingerCurls, bool force=false)

 


void 

SetLessPhysHands (bool newstatus)

 

Sets bLessPhysHands.

 


void 

 


void 

 


void 

 


void 

 


bool 

DoTryGrabbing (FHitResult &Hit, bool ForceInteraction)

 


bool 

TryGrabbing (FHitResult &Hit, bool ForceInteraction)

 


void 

CheckFingerCollisionOverlap (TArray< FName > &FingerSocketsNames, TArray< FName > &FingerBonesNames)

 


void 

UpdateGrabAnimation (UAnimSequence *NewAnimation)

 


void 

UpdateTriggerPressedAnimation (UAnimSequence *NewAnimation)

 


void 

UpdateAPressedAnimation (UAnimSequence *NewAnimation)

 


FORCEINLINE bool 

GetIsGrabbed () const

 


FORCEINLINE bool 

GetHasWeapon () const

 


FORCEINLINE uint8 

GetCaliber () const

 


FORCEINLINE USkeletalMeshComponent * 

GetHandMesh () const

 


FORCEINLINE USkeletalMeshComponent * 

 


FORCEINLINE FVector 

 


FORCEINLINE FVector 

 


FORCEINLINE EControllerHand 

GetHand () const

 


FORCEINLINE UPhysicsConstraintComponent * 

 


FORCEINLINE USceneComponent * 

 


FORCEINLINE AActor * 

 


FORCEINLINE AActor * 

 


FORCEINLINE AActor * 

GetOwnerPawn () const

 


FORCEINLINE bool 

GetAllowAmmo () const

 


FORCEINLINE AVR_HandInventory

GetInventory () const

 


FORCEINLINE bool 

IsClimbing () const

 


FORCEINLINE USphereComponent * 

 


FORCEINLINE UStaticMeshComponent * 

 


void 

EnableLoadingRoom (bool Enable)

 


void 

SetHandIsColliding (bool IsColliding)

 


FORCEINLINE bool 

IsHandClosed () const

 


FORCEINLINE bool 

 


FORCEINLINE FVector 

 


FORCEINLINE FFingerCurls 

 


void 

OnHit (AActor SelfActor, AActor OtherActor, FVector NormalImpulse, const FHitResult &Hit)

 


void 

SetInventoryAccess (bool Access)

 


void 

 


FORCEINLINE FRotator 

 


FORCEINLINE bool 

 


FORCEINLINE bool 

 


FORCEINLINE bool 

 


Public Attributes


bool 

 


bool 

 


bool 

 


bool 

 


bool 

bHitHand = false

 


bool 

 


bool 

 


bool 

 


bool 

 


float 

 


float 

 


float 

 


float 

 


FVector 

 


EControllerHand 

 


Protected Member Functions


void 

 


void 

 


USceneComponent * 

GetNearestGrabComponent (AActor *Actor, FVector TestLocation, bool ForceCheckPriority)

 



bottom of page