Setting Up Hand IK
If you tested the Pawn and IK from the previous section, you noticed that although the head IK works fairly well, if you have motion controllers, the temptation to move your hands is quite strong.
To set it up so that your motion controllers control the hands of the UE4 mannequin, you will use the simple two-bone IK system of UE4. This is because it is nice to have experience with both the FABRIK and two-bone systems, and the IK between the player’s hands and shoulders works quite well with the two-bone system.
Before starting, we will work off of the previous section, so if you haven’t completed that, please do so.
Adding Motion Controllers to Your Pawn
Before you set up the IK for your Pawn, you need to add the Motion Controller Components that will be used to track the player’s hands:
Open the IKPawn from the Blueprints folder.
Add two new Motion Controller Components, the first named MotionController_L and the second MotionController_R.
For MotionController_R, set the Hand variable to Right.
Create two new Static Mesh Components to represent the controllers. These are mainly for debugging purposes.
If you are using Unreal Engine 4.13 or higher, you will have access to the motion controller meshes built into the engine (simply select Show Engine Content in the View options). If this is the case, select the appropriate Static Mesh property for your device for these two newly created Components. (For example, I am using the Oculus Touch, so I selected the OculusControllerMesh Static Mesh.) If you are not using 4.13 or above, simply select a sphere to represent your controllers or import the controller meshes from an external source.
Name these meshes appropriately for your controller (in this case, Touch_L and Touch_R were chosen) and attach these to the appropriate Motion Controller Component. Be sure to invert the Y scale on the right mesh if necessary (see Figure 7.12).
Figure 7.12 Adding motion controllers to the IKPawn
Hand IK Animation Blueprint
Your IKAnimBP class already implements a FABRIK system for the head and spine IK, so now it is time to implement a two-bone IK system for both arms of your skeleton:
Open the IKAnimBP Animation Blueprint and create two new variables, LeftHandWorldPosition and LeftHandWorldRotation, of types Vector and Rotator respectively. For LeftHandWorldPosition, set a default value of (X = 40, Y = 20, Z = 100). This ensures that the mesh has an appropriate preview pose.
Create two more variables named RightHandWorldPosition and RightHandWorldRotation of types Vector and Rotator again. For RightHandWorldPosition set a default value of (X = –40, Y = 20, Z = 100) this time (see Figure 7.13). These will hold the world position and rotation of both motion controllers.
Figure 7.13 IKAnimBP: adding the hand IK variables
Before you start adding the IK setup, you will add two Sockets to the Skeleton. This is because the origin point of the motion controllers does not line up with the hand bone location. This means that you will need to account for an offset when you use IK to get to the motion controller position.
Open the Skeleton editor by clicking on the Skeleton tab inside Persona.
Right-click the hand_l bone in the hierarchy and select Add Socket. Name this Socket hand_lSocket because you will reference it later.
This newly created Socket will initially be at the same position as its parent bone. To change this, select it and in the Details panel change the Relative Location to (X = 13.0, Y = –6.0, Z = –3.5). This places the Socket in the palm of the Skeleton’s hand.
With this new Socket still selected, set its Relative Rotation to 180 degrees in the X-axis.
To test the position of this Socket if you are using Unreal Engine 4.13 or above or have access to the controller mesh of your desired motion controller, right-click the Socket and add a Preview Asset of your controller (see Figure 7.14).
Figure 7.14 IKAnimBP: adding the controller offset Sockets to compensate for the hand bone placement
To make sure you have a Socket for both hands, repeat steps 5 through 8, but this time for the hand_r bone with a Relative Location of (X = –13.0, Y = 6.0, Z = 3.5) and a Relative Rotation of 180 degrees in the Z-axis.
To take advantage of these newly created Sockets, head back to the Animation Blueprint.
Create a variable setter for each of the left- and right-hand position and rotation variables.
Drag off of the CastToIKPawn node and get a reference to the MotionController_L, MotionController_R, and SkeletalMesh Components.
Drag off of the MotionController_L Component reference, call GetWorldRotation, and pass it directly into the LeftHandWorldRotation setter.
For the LeftHandWorldPosition you will need to do a little bit of vector math to subtract the difference between the Socket location and the actual bone location. Drag off of the SkeletalMesh reference and call GetSocketLocation twice.
For the first GetSocketLocation pass in the string hand_lSocket as the In Socket Name parameter, and for the second pass in hand_l (see Figure 7.15). This will get the world location of the hand bone and hand Socket.
Figure 7.15 IKAnimBP: setting the hand variables and offsetting for controller positions in the IK
Drag off of the GetSocketLocation for the Socket and subtract the location of the hand bone. This will give you the relative distance from the hand to the Socket in world space.
Drag off of the MotionController_L reference, call GetWorldLocation, and subtract the relative distance calculated in step 16 from this world location.
Attach the output of this Subtract node to the LeftHandWorldPosition setter.
Repeat steps 13 through 18 but with the MotionController_R reference and the hand_rSocket and hand_r bone. If you need guidance, refer to Figure 7.15.
Attach these setters to the HeadWorldTransform setter already in the graph.
To implement the two-bone IK nodes, you need to head to the Anim Graph:
Once in the Anim Graph, create a new TwoBoneIK node.
Create a getter for your LeftHandWorldPosition variable and attach it to the Effector Location of the two-bone IK.
Pass in (X = 45, Y = –50, Z = 100) to the Joint Target Location. This is a point in Component space toward which the IK rotates. This value was obtained through trial and error, so feel free to change it to suit your needs.
Select TwoBoneIK and change the IKBone to hand_l and the Effector Location Space to World Space (see Figure 7.16).
Figure 7.16 IKAnimBP: left-hand two-bone IK
Create a new Transform (Modify) Bone node, setting the Bone to Modify property to hand_l, the Rotation Mode to Replace Existing, and the Rotation Space to World Space. This will allow you to rotate the hand because the IK will not handle this.
Create a new variable getter for the LeftHandWorldRotation and connect it to the B input of a CombineRotators node.
Pass in 180 degrees to the X value of the A input of this CombineRotators node (see Figure 7.16). This value was obtained by looking at the Skeleton’s initial bone rotation as you did in the “Setting Up Head IK” section.
Connect the output of CombineRotators to the Rotation input of Transform (Modify) Bone.
Repeat steps 2 through 8, replacing the LeftHandWorldRotation and Position with the right-hand variants, (X = –45, Y = –50, Z = 100) as the Joint Target Location, and 180 degrees in the Z for CombineRotators (see Figure 7.17).
Figure 7.17 IKAnimBP: right-hand two-bone IK
Connect these new IK nodes between the Transform (Modify) Bone of the Head IK and the Component to the Local transform and you should be able to play in VR and see a full IK upper body (see Figure 7.18).
Figure 7.18 Upper-body IK example