Workarounds for per-state animation speed control in Mecanim? (Blend trees problematic)

I am trying to scale the speed of a walking animation to match the speed of movement in Mecanim like what was possible with legacy animation (‘animation[“foo”].speed = 0.5f’ or such), but am not finding a good way to do it.

Someone suggested blend trees that blend between the same animation at different timescales, but that has seemed problematic for me. For testing purposes I have a very simple blend tree controlled by a speed value from 0 to 10, with the speed=0 motion being at 0.01 timescale and the speed=10 motion at 1.00 timescale. However, the resulting interpolated timescales seem to be on a dramatic curve, even though the visualization displays a simple linear crossfade. Speeds 0 and 10 work as expected but a speed value of e.g. 5 results in a timescale that looks more like a 0.1 (or even less!) than the ~0.5 it should logically be.

This makes the blend tree useless as a workaround for my purpose. If anyone has any ideas on how to fix this interpolation issue with blend trees or other ideas for achieving the purpose of scaling a specific animation’s speed (not using animator.speed, since that screws up other layers), help would be greatly appreciated.

The problem is that not the time scale is interpolated, the length of the animation is. So having one at time scale 1 with length 2s and one at time scale 10 → length 0.2s, the resulting length when blending 50% is 1.1s which is a time scale of ~1.81 not 5.5.

This interpolation method is not wrong and required for some blending operations but doesn’t result in the correct speed when blending walk animations together.

The interpolation result is correct as long as the length increase of the two blended motions is smaller or equal to a factor of two → speed factor may never be higher than the previous one *2:

(scale_1 / scale_0) <= 2.0

Thus my workaround is to add multiple animation clips with a timescale increment respecting this.
Eg when having an animation with speed 1 and aiming to cover speed 0.1 to 4 you would add:

threshold speed
0.1       0.1
0.2       0.2
0.4       0.4
0.8       0.8
1.6       1.6
3.2       3.2
6.4       6.4

This might not be a good solution when you do it manually, I build the state machines by code and automatically create these blend states.

the new 2d blend trees properly interpolate the clip speeds, so try using one of those with a dummy parameter for the blend axis you don’t need. use the 2D Freeform Cartesian style. Unity, please fix 1d blend trees to work as well as the 2d ones :slight_smile:

I made a script for doing your own interpolation and getting the desired interpolation of time scale.

public class LerpAnimTime : MonoBehaviour {

private float clipLength;

private float speedA;
private float speedB;

private float thresholdA;
private float thresholdB;

public float SpeedToLength(float parameter)
    float cLA = clipLength / speedA;
    float cLB = clipLength / speedB;

    float fraction = (parameter - thresholdA) / (thresholdB - thresholdA);
    float speed = Mathf.Lerp(speedA, speedB, fraction);

    float length = clipLength / speed;
    float result = Mathf.InverseLerp(cLA, cLB, length) * (thresholdB - thresholdA);

    return result;

public float LengthToSpeed(float parameter)
    float cLA = clipLength / speedA;
    float cLB = clipLength / speedB;

    float lerp = parameter / (thresholdB - thresholdA);
    float length = Mathf.Lerp(cLA, cLB, lerp);

    float speed = clipLength / length;

    float fraction = Mathf.InverseLerp(speedA, speedB, speed);
    return fraction * (thresholdB - thresholdA) + thresholdA;


You just pass SpeedToLength what you would normally pass to the animator and it returns what you actually should pass to the animator. LengthToSpeed is the inverse.