This is just a short tutorial to demonstrate how I've implemented separate head and eye look at tracking for human characters, as shown here:
You can also download an example project to dissect how it works. The example project was created in version 4.15 of Unreal Engine.
Note that the example project uses a simple character created in MakeHuman. It's not the same character that appears in the video above or the screen shots below.
To follow along you'll need to have a skeletal mesh with at least a head bone as well as bones for each of the eyes. It's also helpful to have a bone (or socket) right between the eyes of the character for more accurate results. This will be the location that the look at rotation is calculated from so having it between the eyes works best from what I've seen.
It's also easier if the bones of your characters skeleton are zero'd out.
In this example I'll be using one of Genesis 3 characters from Daz Studio. The Genesis 3 skeleton has a bone called CenterBrow which is basically between the eyes. It also has two neck bones which I'll also be using later on, but the neck bones aren't strictly necessary.
You'll also need to have a Character Blueprint and an Animation Blueprint set up properly for your character. I won't go into how to set these up as there are heaps of other tutorials on how to do this.
Let's get start!
The first thing we're going to do is create one structure and a couple of blueprint functions that we will use to calculate the look at rotations for a characters head and eyes.
Because these can be shared across multiple characters I like to place them into a common location in the content browser. For example, Characters -> Common
So let's create a structure that we will use to define the rotation limits and the speed for the head and eyes of the character. I'm going to create a structure called STR_RotationConstraint and I'm going to place it under Common -> Characters -> DataTypes
The structure contains seven fields which are all floats, as in the image below:
As you can see, the structure will allow us to define the limits that the characters head and eyes can rotate around each axis as well as the speed that they can rotate.
Next I'm going to create a blueprint function library that will contain some reusable functions for calculating a characters look at rotations.
I'm going to call the blueprint function library BFL_Characters and I'm going to place it under Characters -> Common -> Blueprints
Now open up the blueprint function library and create a new function called RemapLookAtRotator. Add a single input called InRotator and a single output called OutRotator. Both should be of the type Rotator... obviously.
Now set the function up as it appears in the image below.
This function takes an incoming rotator and returns it so that it is always mapped to a -180 to 180 range as opposed to a 0 to 360 range.
Now create another function called CalculateLookAtRotations and set up the inputs and outputs as they appear below:
Now for the hard part. Set the function up as it appears in the image linked to below. Sorry but I don't know how else to convey large blueprints online.
This is the function where most of the work happens but the function is actually fairly straight-forward.
In the Calculate raw look at rotation section, it's basically finding the look at rotation from the specified bone (in this example it will be the CenterBrow bone) to the target (which is just a vector in world space). We subtract the characters world space rotation and then remap the resulting rotation into a -180 to 180 range. The end result is a rotation whereby 0 is always directly in front of the character, regardless of the characters rotation in world space.
In the Calculate constrained head rotation section we're simply clamping the rotation between the values defined in the incoming STR Rotation Constraint structure. We'll be defining this in the next steps.
In the Set head rotation section we're just lerping between the current head rotation and the new rotation using the speed value defined in the incoming STR Rotation Constraint structure.
In the Calculate raw eye look at rotation section where just subtracting the current head rotation from the original raw look at rotation. This is because if the target look at rotation is 60 degrees and the head is already rotated 40 degrees than the eyes only need to rotate the remaining 20 degrees in order.
In the Constrain eye rotation section is the same as with the head where we're just clamping the eye rotation between the values we'll be passing in via the structure we made.
In the last section we're just lerping between between the current eye rotation and the new eye rotation.
Finally we're returning the new head and eye rotations.
Open up your animation blueprint and define some variable as in the image below:
Now, in the event graph of the animation blueprint we'll call the calculate look at rotations function and use the results to update the local variables we just created, as in the image below.
We're going the leave the Animation Blueprint for now and jump over the the Character Blueprint.. but we'll be coming back to the Animation Blueprint in the final steps.
Open up your character blueprint and define two variables as in the image below. The first is a reference to your characters Anim Blueprint and the second is an Actor reference. Make the Actor reference public so that we can pick a look at target in your scene.
Note: how you determine what your character should be looking at is up to you but for this simple demonstration we'll just be adding a Sphere to the level and selecting that as the look at target.
The rest of the character blueprint is very simple. Just store a reference to your animation blueprint on the Begin Play event and then pass the current world space location of the look at target to your animation blueprint on Tick event (or however often you want o update it's location).
That's it for the character blueprint.
In your map, add a Sphere and then select it as the Look At Target for your character.
Almost done. The only thing left to do is set up your animation graph so that the calculated head and eye rotations are applied to your characters skeleton.
Open up your animation blueprint again and go to the anim graph.
Here is what the anim graph for this simple demo looks like:
Starting from the Remap look at rotations section on the left hand side, because the bones for the Genesis 3 skeleton come in rotated 90 degrees, I'm simply remapping the axis to suit the Genesis 3 skeleton. Depending on the skeleton you're using you may be able to skip this part and just pass the look at rotations through directly.
In the Apply dynamic look at rotations section of the anim blueprint, I'm applying the head look at rotation to the neckLower, neckUpper and head bones, using the Transform Modify Bone nodes.
The for each of the Transform Modify Bone nodes are quite simply. We just specify the bone we want to affect and then set Rotation Mode to Replace Existing and Rotation Space to Bone Space.
These properties are the same for all of the Transform Modify Bone nodes. The only thing that changes between them in the bone that is being affected.
We do the exact same thing with the eye look at rotation and the left and right eye bones.
Finally, we use a Layered blend per bone node to combine the look at rotations together with any existing animations.
For the Layered blend per bone node we add five elements to the Layer setup, one for each of the five bones. For the neckLower, neckUpper and head bones I set the Blend depth to 1. For the two eye bones I set the Blend depth to 0.
The last thing I've done here is the spread the weight of the head look at rotation across the two neck bones and the head bone. If you 100% of the head look at rotation applied to each of those three bones then your characters head will overshoot the look at target. The reason for this is because the neckUpper bone is a child of the neckLower bone and so will inherit any rotation applied to the nectLower bone. Likewise, the head is a child of the neckUpper bone and so it will inherit any rotation applied to both the neckLower and neckUpper bones.
To prevent this from happening, I spread the weight of the head look at rotation across all three bones so that the total weight equals 1 (or 100% of the rotation).
In the image above you can see that I've set the weight for the necklower bone to 0.1 so that it only receives a small amount of the total rotation. I then set the weight of the neckUpper bone to 0.3. Finally I set the weight of the head bone to 0.6.
The eye bones don't have this problem so they both have their weights set to 1.
That it!! You should now be able to simulate the scene and drag the look at target around and your characters head and eyes should continually track the target.