# How weights of 2D Blending are calculated?

![alt text][1]Could you share information about how weights of 2D Blending are calculated. I've done 1D Blending. but have problems with 2D Freeform Cartesian. Even pseudo code sharing will be of help.

I also found function

```
public static extern void CalculateRootBlendTreeChildWeights (Animator animator, int layerIndex, int stateHash, float[] weightArray, float blendX, float blendY);
```

but is in namespace UnityEditorInternal.

Thx

Example. Circles around Motion.positions are weights. How they are calculated? What algorithm is used. [1]: /storage/temp/72664-screen-shot-2016-06-22-at-120911-pm.png

### People who like this

**Answer** by runevision
·
Jun 27, 2016 at 03:30 PM

The 2D Freeform Cartesian blend type is based on the Gradient Band interpolation described in chapter 6.3 of my Master's Thesis.

The 2D Freeform Directional blend type is based on the Gradient Bands in Polar Space interpolation described in chapter 6.3.1.

A PDF version of my thesis is available here: http://runevision.com/thesis/

**Answer** by SarperS
·
Jun 22, 2016 at 10:07 AM

One example is, say you want to blend between 4 different animations for your character's horizontal movement (forward, back, left strafe, right strafe). What you do is, you take the character's velocity, transform it into character's local transform space, normalize it. It gives you a velocity vector relative to the character's direction, a vector where you can see where the body is moving towards relative to the direction it faces, so you can tell if it's strafing or moving backwards etc.

So you feed this resulting vector into your 2D blending tree with the 4 animations set up correctly at Forward (Y:1) Backward (Y:-1) Right (X+1) Left (X-1) and it blends between those 4 animations. If the relative velocity vector is (0.5, 0, 0.5) the animation forward and right strafe will both play at 0.5 blend weight (If you set the max blending values at 1.0 that is).

**Answer** by winxalex
·
Jun 22, 2016 at 08:31 PM

I think u are speaking about 2D Simple Directional, and I was more interested to FreeForm and Cartesian flavour, but even this if you experiment with red dot can see that blue points weights depend of distance to red dot(input) and also I think to angular distance. So if we use Formula 1/d1/(1/d1+1/d2+1/d3...) d1 can be just distance or combination of distance + angular distance....

```
void UpdateSimpleDirectional2D(ref float[] inputs, RuntimeBlendTree runtimeBlendTree) {
int numChildren;
if (runtimeBlendTree.children == null || (numChildren = runtimeBlendTree.children.Length) == 0) return;
AnimationMixerPlayable animationMixerPlayable = runtimeBlendTree.mixerPlayable;
if (numChildren == 1) {
animationMixerPlayable.SetInputWeight(0, 1f);
}
__inputVector2.x = inputs[runtimeBlendTree.index0];
__inputVector2.y = inputs[runtimeBlendTree.index1];
#if DEBUG
//__inputVector2.x=0.5f;
if(showLog){
Debug.Log("RuntimeBlendTree "+runtimeBlendTree+" "+runtimeBlendTree.blendType+" numChildren="+runtimeBlendTree.children.Length);
Debug.Log("Input Vector: "+__inputVector2);
}
#endif
//FORMULA // 1/dc /(1/di+1/di+1+1/dc+..1/dn)
//dc - distance of "c" point to "input" point
//FORMULA // 1/ac /(1/ai+1/ai+1+1/ac+..1/an)
//ac - angular distance of "c" point to "input" point
float[] sqrDistancesToInput = new float[numChildren];
float[] angleDistancesToInput = new float[numChildren];
int i = 0;
float weight = 0f;
float currentSqrDistanceToInput;
float currentAngleDistanceToInput;
float sqrDistanceToInputSum = 0f;
float angleDistanceToInputSum = 0f;
RuntimeChildMotion childMotion;
//calculate distances of every childMotion.position to input
for (; i < numChildren; i++) {
childMotion = children[i];
currentSqrDistanceToInput = (__inputVector2 - childMotion.position).sqrMagnitude;
if (currentSqrDistanceToInput > 0) {
//??? Could I bind together this distances together??
//currentAngleDistanceToInput=Vector2.Angle(__inputVector2,childMotion.position);
//cosinus similarity from -1f to -1f shifted to 0 to 1f( same angle cosinus similarity=0f and max opposite direction -1f)
currentAngleDistanceToInput=(Mathf.Clamp(Vector2.Dot(__inputVector2.normalized,childMotion.position.normalized),-1f,1f)-1f)*(-0.5f);
// 1/d1+1/d2+1/d3...
sqrDistanceToInputSum+=1/currentSqrDistanceToInput;
if(currentAngleDistanceToInput>0)
angleDistanceToInputSum+=1/currentAngleDistanceToInput;
sqrDistancesToInput[i] = currentSqrDistanceToInput;
angleDistancesToInput[i]=currentAngleDistanceToInput;
}
else {
//input is same with childMotion.position
//reset all to min weight
for (int j = 0; j < numChildren; j++) {
animationMixerPlayable.SetInputWeight(j, 0f);
}
//maximum weight of playable channel where input(value/position) and childMotion.position overlapped
animationMixerPlayable.SetInputWeight(i, 1f);
#if DEBUG
if(showLog){
for (int j = 0; j < numChildren; j++)
Debug.Log(j+": "+((Playable.GetTypeOf(animationMixerPlayable.GetInput(j)) is AnimationClipPlayable) ? animationMixerPlayable.GetInput(j).CastTo<AnimationClipPlayable>().clip.name : "")+" w="+animationMixerPlayable.GetInputWeight(j));
}
#endif
return;
}
}
for (i = 0; i < numChildren; i++) {
//
//
childMotion = children[i];
//reuse currentSqrDistanceToInput var
// 1/d1 /(1/d1+1/d2+..1/dn)/1 => 1/(d1*(1/d1+1/d2+..1/dn))
//(d1*(1/d1+1/d2+..1/dn))
currentSqrDistanceToInput = sqrDistanceToInputSum * sqrDistancesToInput[i];
currentAngleDistanceToInput=angleDistanceToInputSum * angleDistancesToInput[i];
//1/(d1*(1/d1+1/d2+..1/dn))
if(currentSqrDistanceToInput>0 && currentAngleDistanceToInput>0)
weight = (1 / currentSqrDistanceToInput)*0.5f + (1/currentAngleDistanceToInput)*0.5f;
else if(currentSqrDistanceToInput>0)
weight = (1 / currentSqrDistanceToInput)*0.5f + 0.5f;//have same direction so 0.5f
else
weight=0;
animationMixerPlayable.SetInputWeight(i, weight);
#if DEBUG
if(showLog){
Debug.Log(i+": "+((Playable.GetTypeOf(animationMixerPlayable) is AnimationClipPlayable) ? animationMixerPlayable.CastTo<AnimationClipPlayable>().clip.name : "")+" w="+animationMixerPlayable.GetInputWeight(i));
}
#endif
RuntimeBlendTree blendTree = childMotion.subTree;
if (blendTree != null) {
blendTree.UpdateWeights(ref inputs, blendTree);
}
}
}
```

### Unity Answers is in Read-Only mode

Unity Answers content will be migrated to a new Community platform and we are aiming to launch a public beta by June 9. **Please note, Unity Answers is now in read-only so we can prepare for the final data migration.**

For more information and updates, please read our full announcement thread in the Unity Forum.