Общая информация
Description
VR Hand Component represents the player's hand in a VR environment. It utilizes physics for realistic interactions and employs physics constraints to achieve accurate physics-based behavior. The class is derived from UVR_MotionControllerComponent.
Main Features
Physics Interactions
Finger Collision
Weapon Interactions
Equipment Interactions
Finger IK (Inverse Kinematics)
Hand Animations
Menu Functionality
Radial Inventory Support
Pull Grab Functionality (Gravity Pull and Direct Pull)
Getting Started Guide
Creating the VR Hand Component Blueprint 🎨
You have two options to set up the VR Hand Component:
Option 1: Create a New Blueprint
Create Blueprint: Create a new Blueprint derived from UVR_HandComponent.
Setup: Configure the component from scratch according to your project's needs.
Option 2: Use the Existing Blueprint
Use Existing: Utilize the preconfigured Blueprint provided in the Demo Content folder.
Benefit: This Blueprint is already set up for easy integration and can be customized further.
Adding the VR Hand Component to Your Actor
Add Component: In your VR Player class/BP , select the UVR_HandComponent class/BP.
Customization and Setup
Visual Customization 🎨
Customize the appearance of the VR hand and related elements under the Visualization category:
Hand Mesh: Assign a skeletal mesh for the hand (e.g., SK_VR_Robot_Hand or your custom hand model).
Hand Collision Mesh: Set up a collision mesh for precise interactions.
Teleport Cylinder Mesh: Customize the visual indicator for teleportation destinations.
Teleport Arrow Mesh: Change the appearance of the teleport direction arrow.
Menu Cursor Mesh: Customize the cursor used during menu interactions.
Room Scale Mesh: Adjust the visualization of room-scale boundaries.
Animation and Finger IK Setup 🎬
Achieve realistic hand and finger movements by setting up animations and IK:
Step 1: Select Animation Blueprints
Assign Blueprints: Assign animation Blueprints to RealHandMesh and FakeHandMesh.
Requirement: These Blueprints should be derived from UVR_HandAnimationInstance.
Step 2: Choose Open and Closed Hand Animations
Open Hand Animation: Assign an animation for the open hand pose (a stretched hand works best).
Closed Hand Animation: Assign an animation for the closed fist pose.
Purpose: These animations are essential for natural grabbing and releasing actions.
Step 3: Set Tip Sockets for Each Finger
Assign Sockets: Under Tip Sockets, assign the socket names for each fingertip based on your hand skeleton.
Precision: This enables precise finger movement and collision detection.
Step 4: Adjust Finger IK Settings
NumSamplePoints: Specify the number of segments or traces for each finger to control bending smoothness.
IkTraceCapsuleRadius: Set the trace capsule radius for IK calculations.
Step 5: Run Finger IK Setup
Automate IK: Use the RunFingerIKSetUp button or change any setting to automate the finger IK setup process.
Finger Collision Setup 🛡️
Enhance interaction accuracy with proper finger collision setup:
Step 1: Specify Hand Collision Mesh
Set Collision Mesh: Assign the collision mesh for the hand to enable precise environmental interactions.
Step 2: Place Tip/Start Sockets
Position Sockets: Place the FingerStart and FingerTip scene components at the base and tip of each finger on the hand skeleton.
Components:
ThumbFingerStart and ThumbFingerTip
IndexFingerStart and IndexFingerTip
MiddleFingerStart and MiddleFingerTip
RingFingerStart and RingFingerTip
PinkyFingerStart and PinkyFingerTip
Hand Physics and Constraints Configuration ⚙️
Configure physics settings to simulate realistic hand behavior:
Physics Constraints Overview
HandPhysicsConstraintInstance: Active when the hand is colliding; connects FakeHandMesh and PhysicsHandSocket.
HandPhysicsConstraintPDInstance: Active when the hand is not colliding; provides smoother movement.
PickPhysicsConstraintInstance: Manages object grabbing mechanics.
Constraint Parameters
LinearForceLimit and AngularForceLimit: Control the maximum forces applied to the hand.
LinearPositionStrength and AngularPositionStrength: Adjust the strength of position constraints.
LinearVelocityStrength and AngularVelocityStrength: Control the responsiveness of hand movements.
Interpolation Speeds:
LinearPositionInterpSpeed
LinearVelocityInterpSpeed
Drag Curve
Assign DragCurve: In the Physics settings, assign a DragCurve to manage constraint behavior based on the distance between the hand and controller.
Note: A curve is necessary.
Pull Grab Functionality 🧲
Enable the ability to pull distant objects toward the hand:
Step 1: Enable Pull Grab
Activate: Set bCanPullGrab to true to enable pull grabbing.
Step 2: Select Pull Grab Type
Options:
Gravity Pull: Objects are smoothly pulled toward the hand (similar to Half-Life: Alyx).
Direct Pull: Objects move directly to the hand's location (similar to Boneworks).
Step 3: Configure Pull Parameters
PullGrabDistance: Maximum distance to initiate a pull grab.
PullCheckDelay: Interval between pull grab checks.
DirectPullGrabDistance: Specific distance setting for direct pulls.
DirectPullCurve: Assign a curve for smoothing direct pulls.
Inventory and Menu Setup 📋
Integrate menu systems and radial inventory support:
Menu Settings
Enable Menu: Set bTurnOnSpawnableHandMenu to true to activate menu functionality.
Assign Classes:
MainMenuClass: Assign the class to use for the main menu.
PauseMenuClass: Assign the class to use for the pause menu.
MenuLoadingWidgetClass: Assign a widget class for the loading indicator when accessing menus.
MenuGrabAnimation: Optionally specify an animation for menu interactions.
Radial Inventory
CA_Inventory Component: Use the CA_Inventory (UChildActorComponent) to manage the hand's radial inventory.
Activation: Press the thumbstick button on the right controller to access the radial inventory.
Setup: Assign the appropriate class to CA_Inventory and configure inventory items as needed.
Component Hierarchy and Descriptions
Hierarchical Structure
RootScene (USceneComponent)
The root component of the hand, serving as the base for all other components.
Hands (USceneComponent)
Contains all hand-related components.
HandSocket (USphereComponent)
Serves as a socket for the non-physical hand mesh.
FakeHandMesh (USkeletalMeshComponent)
A non-physical skeletal mesh representing the hand when not interacting with physics objects.
ArcNiagara (UNiagaraComponent)
Used for teleportation arcs.
WidgetInteractionComponent (UWidgetInteractionComponent)
Facilitates interaction with UI widgets.
PhysicsHandSocket (USphereComponent)
Serves as a socket for the physical hand mesh and simulates physics.
RealHandMesh (USkeletalMeshComponent)
The physical hand mesh that interacts with physics objects.
Finger Collisions (UCapsuleComponent)
ThumbFingerCollision
IndexFingerCollision
MiddleFingerCollision
RingFingerCollision
PinkyFingerCollision
Finger Scene Components (USceneComponent)
Start and tip components for each finger (e.g., ThumbFingerStart, ThumbFingerTip).
GrabRoot (USceneComponent)
Base component for grabbing functionality.
GrabDirection (UArrowComponent)
Indicates the direction for grabbing actions.
CA_Inventory (UChildActorComponent)
Manages the hand's radial inventory.
MenuWristLoader (UWidgetComponent)
Displays the menu loading bar.
RealHandCollision (UStaticMeshComponent)
Provides collision for the physical hand mesh.
ArcDirection (UArrowComponent)
Determines the direction of the teleportation arc.
PullDirection (UArrowComponent)
Indicates the direction for pull grabbing.
ArcEndPoint (UStaticMeshComponent)
Represents the end point of the teleportation arc.
MenuCursor (UStaticMeshComponent)
Displays the cursor during menu interactions.
TeleportCylinder (UStaticMeshComponent)
Visualizes the teleportation destination area.
Arrow (UStaticMeshComponent)
Shows the teleportation direction.
RoomScaleMeshComponent (UStaticMeshComponent)
Outlines the room-scale boundaries.
WidgetSphereMesh (UStaticMeshComponent)
Used for widget interactions.
PullVisualizer (USceneComponent)
Visualizes the pull grab effect.
DirectPullTimeLine (UTimelineComponent)
Manages the timing for direct pull animations.
Tick Algorithm Overview
The VR Hand Component performs various functions each frame to ensure smooth interactions:
HandPhysicsTick
Manages physics constraints based on collision status.
Switches between HandPhysicsConstraintInstance and HandPhysicsConstraintPDInstance.
CheckAimToGrab
Moves the hand closer to nearby grabbable objects using physics constraints.
UpdateHandAnimation
Updates hand animations based on input and interactions.
Adjusts finger poses using IK.
UpdateRoomScaleOutline
Adjusts the room-scale boundary visualization relative to the teleport destination.
CheckMenuStatus
Manages menu activation and adjusts hand visibility and functionality accordingly.
UpdateWidgetCursor
Moves the cursor on UI widgets during interactions.
CheckHandsAndControllerDist
Ensures the hand stays within a reasonable distance from the controller.
Adjusts physics constraints if necessary.
CheckControllerAndPickDist
Drops held objects if they are too far from the controller.
CheckGrabPossibility
Verifies if grabbing is possible based on object weight, distance, and player input.
CheckMenuButtonPress
Monitors the duration of menu button presses to trigger menu actions.
UpdateAllFingersCollision
Recalculates finger collisions based on the current hand pose.
MakeUpdateWidgetLookAtCamera
Keeps the menu or UI widget facing the player.
The VR Hand Component uses three physics constraints managed via FConstraintInstance:
HandPhysicsConstraintInstance: Connects the FakeHandMesh and PhysicsHandSocket when the hand is colliding.
HandPhysicsConstraintPDInstance: Used when the hand is not colliding.
PickPhysicsConstraintInstance: Manages object grabbing mechanics.
These constraints are dynamically switched in HandPhysicsTick based on the hand's collision status. All relevant components have "Simulation Generates Hit Events" enabled for proper functionality.
Hand Skeleton
Skeleton Compatibility: Supports both SteamVR and Unreal Engine XR skeletons.
Settings:
Reflect Left Hand: Mirrors the hand model for the left hand.
Using Steam VR Skeleton: Enables compatibility with SteamVR skeleton.
Finger Bones: Configurable bone names for each finger to ensure accurate finger collision and IK.
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).
Line traces for Grab IK(Technical info)
Hand uses line traces 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).
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)
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 Hand Inventory for more information).
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.).
Справочник API Blueprint
Public Member Functions | |
| AVR_Hands () |
| |
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 | SetParentMotionController (UVR_MotionControllerComponent *MotionController) |
| |
void | |
| |
void | |
| |
void | |
| |
bool | |
| |
void | GrabActor () |
| If grab button is pressed. |
| |
void | ReleaseActor () |
| 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 | ClearArc () |
| 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 | Index_Touch () |
| 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 () |
| A Pressed. |
| |
virtual void | A_Released () |
| A Released. |
| |
virtual void | B_Pressed () |
| B Pressed. |
| |
virtual void | B_Released () |
| 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 | WakePhysics () |
| |
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 | SpawnMenu () |
| |
void | DestroyMenu () |
| |
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 * | GetFakeHandMesh () const |
| |
FORCEINLINE FVector | GetHandLocation () const |
| |
FORCEINLINE FVector | GetControllerLocation () const |
| |
FORCEINLINE EControllerHand | GetHand () const |
| |
FORCEINLINE UPhysicsConstraintComponent * | GetPhysicsConstraint () const |
| |
FORCEINLINE USceneComponent * | GetMCSceneComponent () const |
| |
FORCEINLINE AActor * | GetAttachedActor () const |
| |
FORCEINLINE AActor * | GetLastAttachedActor () const |
| |
FORCEINLINE AActor * | GetOwnerPawn () const |
| |
FORCEINLINE bool | GetAllowAmmo () const |
| |
FORCEINLINE AVR_HandInventory * | GetInventory () const |
| |
FORCEINLINE bool | IsClimbing () const |
| |
FORCEINLINE USphereComponent * | GetPhysicsHandSocket () const |
| |
FORCEINLINE UStaticMeshComponent * | GetHandCollision () const |
| |
void | EnableLoadingRoom (bool Enable) |
| |
void | SetHandIsColliding (bool IsColliding) |
| |
FORCEINLINE bool | IsHandClosed () const |
| |
FORCEINLINE bool | GetIsUsingSteamVRSkeleton () const |
| |
FORCEINLINE FVector | GetPhysicsClimbVector () const |
| |
FORCEINLINE FFingerCurls | GetFingerCurls () const |
| |
void | OnHit (AActor SelfActor, AActor OtherActor, FVector NormalImpulse, const FHitResult &Hit) |
| |
void | SetInventoryAccess (bool Access) |
| |
void | SetInventoryBox (UVR_InventoryBox *InventoryBox) |
| |
FORCEINLINE FRotator | GetInitialControllerRotation () const |
| |
FORCEINLINE bool | GetIsValidTeleportDestination () const |
| |
FORCEINLINE bool | GetIsTeleporterActive () const |
| |
FORCEINLINE bool | HasInventoryAccess () const |
|
Public Attributes | |
bool | |
| |
bool | |
| |
bool | |
| |
bool | |
| |
bool | bHitHand = false |
| |
bool | HandIsColliding = false |
| |
bool | |
| |
bool | |
| |
bool | |
| |
float | |
| |
float | |
| |
float | |
| |
float | |
| |
FVector | |
| |
EControllerHand | |
|
Protected Member Functions | |
void | |
| |
void | |
| |
USceneComponent * | GetNearestGrabComponent (AActor *Actor, FVector TestLocation, bool ForceCheckPriority) |
|