8-Way Animation Blending

I’ve made some run animations for a character and I’m having some difficulty implementing them. There are 8 separate animations that each correspond to a possible run direction using the WASD keys. They are forward, back, left strafe, right strafe, and the four in-between animations. Just using the four main animations(forward, back, left, right) would be easy - just set the weight to vertical and horizontal input, but I can’t seem to wrap my head around how to implement the in-between animations. I am using Input.GetAxis for the input, so the input will be smoothed.

Any advice on how to proceed with this?

In my game, I blend the animations (6, since I am on a hex grid) based on the angle between the look direction and the move direction, not directly via the input.

function Update () {
 lastPos = curPos;
 curPos = transform.position;
 
 if(curPos != lastPos){
 curAngle = Vector3.Angle((curPos - lastPos).normalized, transform.forward);
 clockwise = angleDir(transform.forward, (curPos - lastPos).normalized, Vector3.up);
 if(curAngle < 30)
 animation.CrossFade("walk_F", 0.1);
 else if(curAngle > 30 && curAngle < 90 && clockwise < 0) 
 animation.CrossFade("walk_FL", 0.1);
 else if(curAngle > 30 && curAngle < 90 && clockwise > 0) 
 animation.CrossFade("walk_FR", 0.1);
 else if(curAngle > 90 && curAngle < 150 && clockwise < 0) 
 animation.CrossFade("walk_BL", 0.1);
 else if(curAngle > 90 && curAngle < 150 && clockwise > 0) 
 animation.CrossFade("walk_BR", 0.1);
 else if(curAngle > 150) 
 animation.CrossFade("walk_B", 0.1);
 }
 
 if(curPos == lastPos)
 animation.CrossFade("idle", 0.1); 

function angleDir(fwd: Vector3, targetDir: Vector3, up: Vector3) {   //determines CW or CCW
 var perp: Vector3 = Vector3.Cross(fwd, targetDir);
 var dir: float = Vector3.Dot(perp, up);
 
 if (dir > 0.0) {
 return 1.0;
 } else if (dir < 0.0) {
 return -1.0;
 } else {
 return 0.0;
 }
}

There are no real blends between the animations here, since the player can only move in distinct directions, but it should be quite simple to implement…

What you want to do is use animation.Blend(“animname”, weight) and calculate your weight depending on what’s important for you.

For us, we had a 4 way blend and we use the heading angle to calculate the correct blend weight:

  1. get blending angle in radians
  2. calculate sine and cosine
  3. save sign of sine and cosine
  4. animation.blend(“forward”, Mathf.Clam01(cosSign * cosinevalue^2))
  5. animation.blend(“up”, Mathf.Clam01(sineSign * sinevalue^2))
  6. animation.blend(“back”, Mathf.Clam01(cosSign * cosinevalue^2 * -1))
  7. animation.blend(“down”, Mathf.Clam01(sineSign * sinevalue^2 * -1))

This will give you values between 0-1 for each animation and will let you blend between.