Inverse Kinematics

The most common form of animation uses Forward Kinematics where each bone is given a specific rotation which it adds to the rotation of its parent. So you rotate the shoulder and the elbow moves accordingly because it is a child of the shoulder. You rotate the elbow and the hand moves accordingly. And so on.

But sometimes it is desirable to directly control the end point instead. With Inverse Kinematics, you specify the desired position of a hand or foot and the IK system figures out how to rotate the bones to get it there. This can be used to have a hand reach a specific point such as a door handle or adjusting the height of a foot to match the terrain.

Animancer allows you to use Unity's inbuilt Humanoid IK system in mostly the same way you would with Mecanim. The main difference is that you enable it by setting AnimancerNode.ApplyFootIK or AnimancerNode.ApplyAnimatorIK on a state or layer instead of enabling it with toggles in an Animator Controller.

You can also enable/disable IK using the Context Menu Functions in the AnimancerComponent Inspector for testing purposes (the setting will not be stored in the scene or prefab, so you will always need to enable Ik with a script to use it at runtime).

The Inverse Kinematics examples demonstrate the use of this feature.

IK Pass

The IK Pass causes Unity to call the OnAnimatorIK(int layerIndex) method every frame in any scripts attached to the same object as the Animator.

void EnableIKPass(AnimancerComponent animancer, AnimationClip clip)
{
    // Enable IK Pass for all states:
    animancer.Playable.ApplyAnimatorIK = true;

    // Enable IK Pass for all states on a specific layer:
    animancer.Layers[0].ApplyAnimatorIK = true;

    // Enable IK Pass for a specific state (and any children if it is a mixer):
    var state = animancer.States.GetOrCreate(clip);
    state.ApplyAnimatorIK = true;
}

This is equivalent to the IK Pass toggle in an Animator Controller layer, except that due to limitations in the Playables API the layerIndex Unity passes into OnAnimatorIK will always be zero:

By default, states will automatically be given the IK Pass setting from their parent when it is assigned (such as when creating a new state or moving it to a different layer). This can be prevented by setting AnimancerNode.ApplyParentAnimatorIK = false; before changing the parent.

Foot IK

Foot IK allows Unity to make the character's feet more closely match the original animation's positions after retargeting it from the animation's rig to the model's rig. This can help reduce foot sliding caused by differing rig proportions, but it also often has undesirable results so it should be selected on a case by case basis.

void EnableFootIK(AnimancerComponent animancer, AnimationClip clip)
{
    // Enable Foot IK for all states:
    animancer.Playable.ApplyFootIK = true;

    // Enable Foot IK for all states on a specific layer:
    animancer.Layers[0].ApplyFootIK = true;

    // Enable Foot IK for a specific state (and any children if it is a mixer):
    var state = animancer.States.GetOrCreate(clip);
    state.ApplyFootIK = true;
}

This is equivalent to the Foot IK toggle in an Animator Controller state:

By default, states will automatically be given the Foot IK setting from their parent when it is assigned (such as when creating a new state or moving it to a different layer). This can be prevented by setting AnimancerNode.ApplyParentFootIK = false; before changing the parent.

Animated Properties

This is a Pro-Only Feature: you can try it out in the Unity Editor with Animancer Lite, but it will not be available in runtime builds unless you purchase Animancer Pro.

The AnimatedBool, AnimatedFloat, and AnimatedInt classes allow you to access the values of custom curves in your animations at runtime. This is often used to control the weight of the IK so that some parts of the animation use more IK than others. 0 means the limb will be fully controlled by the animation while 1 means the IK system will be fully in control, with anything inbetween giving a proportional amount of control.

[SerializeField] private AnimancerComponent _Animancer;

private AnimatedFloat _FootWeights;

private void Awake()
{
    _Animancer.Layers[0].ApplyAnimatorIK = true;

    _FootWeights = new AnimatedFloat(_Animancer, "LeftFootIK", "RightFootIK");
}

private void OnAnimatorIK(int layerIndex)
{
    // [0] is the first name we passed into the constructor:
    float currentLeftFootWeight = _FootWeights[0];

    // [1] is the second name we passed into the constructor:
    float currentRightFootWeight = _FootWeights[1];

    ...
}

The Uneven Ground example demonstrates the use of this feature in more detail.

Adding custom curves to an animation is done differently depending on where it's located:

In an Animator Controller, you can access a custom curve by creating a Float Parameter with the same name as the curve. Then it will automatically update that parameter every frame with the value of the curve at the current time so you can access it in a script using animator.GetFloat("Parameter Name").

Exposed Curves

Before Animated Properties were implemented, previous versions of Animancer allowed access to custom curves by using using an ExposedCurve class to extract a curve from the AnimationClip in the Unity Editor and serialize it separately so that it can be accessed directly at runtime. That class can now be downloaded from here and using it is fairly straightforward:

  1. Create an ExposedCurve using Assets/Create/Animancer/Exposed Curve.
  2. Assign the AnimationClip containing the curve and enter the Property Name of the curve.
  3. Any future changes to the original curve in the AnimationClip will automatically be retrieved by the ExposedCurve. Unfortunately it is not currently possible to edit the curve using the ExposedCurve Inspector. You need to edit the curve in the Animation window or the model import settings.
  4. Reference that asset in your script and evaluate it during OnAnimatorIK to determine how much weight to give the IK system during each frame:
[SerializeField] private AnimancerComponent _Animancer;
[SerializeField] private ExposedCurve _RightFootWeight;

private void OnAnimatorIK(int layerIndex)
{
    var currentWeight = _RightFootWeight.Evaluate(_Animancer);

    ...
}

Note that an ExposedCurve can only evaluate the target curve from a single animation where an Animated Property will automatically Blend the value according to all the animations currently playing.