After some time i want to share my IK foot setup working with default UE4 mannequin.
At beginning i was planning to release it on marketplace but i’ve changed idea.
I have spent one week to create this project and two day for writing this tutorial.
Main features are:
- Auto adjusted collision capsule height.
- Performance optimized.
- There is no strange legs behavior when running.
Starting with a little bit of theory, I will assume that you have a basic knowledge of what IK (Inverse Kinematics) is.
If not, spend some time to read IK Setup from Unreal Engine.
Most of users dealing with IK on Unreal Engine don’t know how Two Bone IK work and what “Joint Target” is.
Like as Ray Arnett saw on answer hub
Joint Target is basically the equivalent of a pole vector in Max or Maya. For example, on a leg or arm IK setup, the knee or elbow will aim at the Joint Target.Ray Arnett
Look at the left picture, i’m just translating a bone that act like as our Target Joint in UE, Pole Vector in Maya or Pole in Blender
Just to clarify, i will not using the PixxiePane rig for this tutorial though it is much better for IK animations inside the engine.
Now we can proceed with the practical tutorial.
So, lets start by adding sockets for each foot. Leave relative location and rotation at zero values and names like as engine default, so foot_lSocket and foot_rSocket.
Next we will jump to our Animation blueprint, so that we can define variables and setup nodes.
First of all define this variables:
|Type||Variable Name||Default Value|
|LeftJointLoc||Set to a value that look good in anim preview|
|RightJointLoc||Set to a value that look good in anim preview|
Then place and set nodes as following images:
RightEffectorLoc is multiplied by -1 because the right_l bone in the mannequin character is mirrored and so flipped.
Now in my case Joint Target values are (X=-14.463602,Y=28.193642,Z=-15.975664)for left foot and (X=-16.883377,Y=26.909676,Z=14.823689)for right foot.
In your case and for some reason your values can be different, like as i saw previously try to adjust these settings to achieve a good result in the animation preview.
|Type||Variable Name||Default Value|
|IKCapsuleHalfHeight||defined in construction script|
|AnimInstance||Anim Instance BP|
In construction script we will store the default capsule half height to use it later.
I always use to store worlds delta seconds within a variable instead calling “Get World Delta Seconds” as a good practice so that can reduce function calls and reducing connections between nodes.
At this point i will not immediately show the content of IK Graph, instead i will show every IK functions used.
Notice the three local variables with the comment bubble, you can also omit to define these local vars connecting function inputs directly to destination. So, what this function do is casting a line trace from the middle of capsule for Z location and from X and Y foot socket’s locations straight down until to the bottom of the capsule and then subtracting the TraceDistance (Distance) variable value.
Then, if there isn’t a valid hit the function will return just a zero, otherwise the end trace location is subtracted from the trace hit location and successively from TraceDistance, to taking only the distance value from the socket to the hit location.
Then we just add a positive or negative value for adjusting the foot offset because capsule stand always 2 or 3 units higher from the underlying object. This value could be different if you are using different animations or character meshes.
Outputs are simply the foot offset and the impact normal, useful when we will go to adjust the foot rotation to match the floor slope. See next function
This function will convert the trace impact normal vector to rotation.
IKUpdateFootOffset & IKUpdateFootRotation
Not too much to say here, just two utility function to update foot offset and rotation smoothly.
NOTE: EffectorVar and RotationVar variables are passed by reference.
Here we can see that this function take two parameters as input: Hips Shift and Reset To Default.
Basically when the hips/pelvis bone is shifted down there is a significant distance between the top of the collision capsule and the top of the mesh’s head. So the height of the capsule will be always proportionally related to the hips bone translation.
So, the hips offset is “absolutized”, divided by two because capsule height is set by it’s half value and then is subtracted to IKCapsuleHalfHeight defined in construction script.
Function to smoothly reset variables to default or zero values, called when character start moving, useful to reduce brute camera movements also.
This is the big part of this tutorial. So keep ready! Like i saw before, notice the “local var” bubble
Before updating foot effectors in the animation blueprint, Left and Right foot offsets variables are still unclamped. Here we are taking the min value between footoffsets and zero. The smallest value will be used to translate hips bone.
Then, when we have the hips offset, we can update capsule height with the new value.
We are subtracting the hips offset value to each foot effector value. This because if hips bone go up all skeleton go up and, because of this, foot too. So subtracting it’s value to foot effector value will keep foot bones at the established position calculated in the Part 1 of IKUpdate function.
The last part of this function, created mainly for optimizing performances.
We’re just checking that the current foot effector location value from animation blueprint is the same as the one that has just been calculated previously. When both values are equal the custom event DisableIK will be fired.
Here we go. Now i can show you the content of this graph. It’s just a logical graph.
Here we are just checking some conditions to check if character is moving or is turning.
Practically IK work only when character turn on itself even if it is not moving. EnableIK is another custom event in combination with DisableIK previously mentioned.
In this part we can see the gate and events that allow to enable or disable IK.
DisableIK is delayed because if IK will be disabled instantly UpdateIK will not have enough time to update foot locations. IKTimeout variable is the time to wait before disabling IK.
And that’s all. This is our result
I think that it could be more optimized, it need only a good refactoring. Maybe i could extend this project to hands when i will have time.32