Today I am trying to figure out a cheap way to implement Unity’s notion of BlendTrees for blending locomotion animations. Ideally, any number of input animations can be blended together, based on the velocity of the character (with respect to the direction it faces), but in practise, we only have to worry about a maximum of two animations at any moment. It works by defining a ‘characterspace direction’ in 2D for each animation to be blended - essentially we’re distributing animations around a 2D circle which is defined in the unrotated / identity space of the character - ie, relative to the direction that the character is facing.

My current idea goes something like this:

The character is moving with some linear velocity - a 3D vector.

Step number one is to transform that vector into the local space of the character, and drop the Y component, so we can think in terms of a 2D circle, on the XZ plane (and normalize it, so its just a 2D direction with unit length), and think in terms of trigonometry, where zero degrees is our Right vector, and ninety degrees is our Up vector.

Step two: without making assumptions about how many animations are involved?

We find the 2D dot product between the (transformed, 2D) velocity vector, and the direction associated with each animation. We capture the results in an array, and once we have all the dot values, we normalize the array, by dividing each value with the sum of all values. Note that if a dot value is negative, that animation is effectively disabled, and we set the value as zero. The remaining (positive, and normalized) dot values are the weights we should be applying to our animations.

I’m aware that this could be optimized by computing which Quadrant we’re working in, however that introduces a bunch of conditional logic, which is likely to cause the cpu to stall, as the compiler can’t optimize on branched logic. For a fistful of operations, it’s generally faster to avoid the branches, and simply perform operations that were not really necessary for the solution of the problem.

Anyone done any work in this area? I would love to hear your ideas / opinions!