Consuming FXRMotionControllerData in Blueprint

important

Unreal Engine versions 5.2, 5.3, and 5.4 are limited to FXRMotionControllerData since at the time of their release no FXRHandTrackingState was available. Also please keep in mind that, while FXRMotionControllerData is pretty much usable and functional in Unreal Engine 5.5, it is recommended to utilize FXRHandTrackingState instead. This is because this version of UE has deprecated FXRMotionControllerData in favor of the FXRMotionControllerState and FXRHandTrackingState structs. Prior to version 5.5, FXRMotionControllerData handled both motion controller and hand tracking data. From 5.5 onward, these responsibilities have been separated into the two distinct structs, providing clearer and more specialized handling of each.

Before continuing this section, please ensure you've studied the Consuming FXRMotionControllerData section, first.

Drawing and Animating Virtual Hands

  1. Create a new Virtual Reality project based the Unreal VR Template.

  2. Make sure the SenseGlove UnrealEngine plugin is installed and enabled inside your new project.

Enabling the SenseGlove Unreal Engine Plugin

  1. You could use either hand-tracking or a SenseGlove device as the input data, or both of the inside the same project. Whether you would like to use hand-tracking or a SenseGlove device, please make sure the required steps are taken for each of those first.

  2. You could add the required Blueprint code for drawing virtual hands to either your Level Buleprint or the VRPawn Blueprint Class located at /Content/VRTemplate/Blueprints/VRPawn. In this guide we are going to add the code to our VRPawn.

  3. Add a new function named Draw Hand with an input parameter of type EController Hand named Hand.

Adding the Blueprint Draw Hand function

  1. Inside this function's event graph add a Get Motion Controller Data node from SenseGlove > Tracking > XR Tracker > Get Motion Controller Data.

Adding the Get Motion Controller Data node

  1. Then connect the functions Hand input parameter to the Get Motion Controller Data's Hand input and right-click on the OutMotionControllerData parameter and use the Break XRMotionControllerData node to break the struct to it's fields.

Breaking the XR Motion Controller Data node

  1. After this, we need to perform data validation by checking the return status of the Get Motion Controller Data function and FXRMotionControllerData's Valid field. Then, we check if the motion controller device is being tracked and indeed coming from a hand-tracking source. And, finally, we check whether we have the positions and rotations for exactly 26 joints or not.

FXRMotionControllerData validation

  1. OK, now it's time to draw the joints! If we check out the SenseGlove Debug module's draw option, we notice there are various ways to draw the debug virtual hand. Drawing a cube or a gizmo per joint, or draw the whole hand all at once by passing the retrieved FXRMotionControllerData to the DebugVirtualHand::Draw function! But, since the point of this tutorial is to learn how to consume the FXRMotionControllerData we ignore the last option. Between the debug cubes or gizmos, we are going to choose the gizmos since they better represent the rotations than the cubes.

Some options for drawing a debug virtual hand

  1. In the last step inside the Draw Hand function, in order to draw a virtual hand with 26 joints, we have to first iterate through either of the Hand Key Positions or Hand Key Rotations arrays from the FXRMotionControllerData struct. Since we made sure both arrays have 26 elements before we reached this step, it's safe to just iterate over one and use the Array Index inside a For Each Loop or a For Loop to access the position and rotation of every joint. Then we use each array Get (a ref) method to access the position and rotation data inside the loop and call the Draw function from SenseGlove > Debug > Gizmo per every joint. Please note that there are two Draw functions and the only difference between the two is that one accepts an FQuat and the other a FRotator for its Rotation input parameter. In this case, we use the FQuat variant to avoid an extra conversion to FRotator. Also, please adjust the Thickness option for the Settings parameter from 1.0 to 0.2, as the default value might be too thick for drawing a joint gizmo.

Drawing a debug gizmo per each hand's joint

  1. Well, now the full implementation for the Draw Hand function insde the VRPawn should look something like this:

VRPawn Draw Hand function final implementation

  1. Finally, go back to VRPawn's event graph and the following code to the Tick event. Basically what we do here is call our newly implemented Draw Hand twice, once for each hand.

Attempt to draw the left and right virtual hands every frame from the VR Pawn Tick event

  1. Now, go back to the VRTemplateMap and use the VR Preview button to run the game. If everything's done correctly, you should be able to see the virtual hands inside your VR simulation.

FXRMotionControllerData animated debug virtual hands