Astro Kat: Moving Kat (Raycast, IK, Sample Code)
I recently added Hand IK to Kat and thought it would be nice to do an article on movement.

Setting up a third person character controller can be a hassle. 

Everyone will want different things from their controller, but today I want to share how Kat works.

CharacterControllers and Rigidbodies

The first thing to look at is the two most common solutions for a third person character controller; Unity's own CharacterController component, and the Collider + Rigidbody approach.

The character controller is pretty good out of the box. The Rigidbody approach requires more work, but responds to Physics.

A character controller can easily walk up stairs/ slopes. A rigidbody + Capsule collider can't get up at all.

On the other hand, whenever I tried to use a CharacterController I've had weird issues with moving collision, and stuttery movement. (Maybe I'm missing something but this is following Unity's own examples)

Since I want the control and physics of a Capsule Collider + Rigidbody. I use a floating Capsule for basic collision, and set the floor position via raycasts.

So here's a stripped down version of Kat's setup

Basic Movement Setup


 vertical = Input.GetAxis("Vertical");
 horizontal = Input.GetAxis("Horizontal");

Get the input from the Joystick/Arrow Keys/ WASD


Vector3 correctedVertical = vertical * Camera.main.transform.forward;
Vector3 correctedHorizontal = horizontal * Camera.main.transform.right;

Multiply with the camera's forward and right so the character moves according to the camera view


 moveDirection = new Vector3 ((combinedInput).normalized.x, 0, (combinedInput).normalized.z);

Combine the corrected input and normalise it, so movement is the same no matter what direction. Keep the Y input 0 so the character doesnt try to walk into the floor/air.

Rotating towards movement 

 Quaternion rot = Quaternion.LookRotation(moveDirection);
transform.rotation = rot;

Look at the moveDirection and set the rotation

Setting Velocity

rb.velocity=(moveDirection *moveSpeed);

Set the Velocity directly
Since it's a Physics movement, set this in FixedUpdate()

Floor Raycasts

For the floor alignment send out a few raycasts down.

if (Physics.Raycast(origin, -Vector3.up, out hit, 1.6f)){
return hit.point;

Send out one in the middle, and 4 around, by using different offsets to the ray origin. Return the average.

Move Rigidbody

 floorMovement =  new Vector3(rb.position.x, FloorRaycast().y, rb.position.z);

Then move the RigidBody position to the raycast Y position (Still in FixedUpdate()).

The other nice part is that if most raycasts return Vector3.Zero, you can play a balancing animation cause you can be sure its a ledge or other unstable/thin footing.

EDIT: Added a grounded check so you can walk off ledges and fall, not teleport to the floor
Movement Script with Comments :
PasteBin Link 

Attach the CharacterMovement Script and add a Rigidbody, and a Capsule Collider, make sure its off the ground and in the center of the character like in the picture.

Freeze the rotation of the rigidbody and turn off gravity if you're seeing stuttering, the gravity is applied manually when not grounded

And to prevent sticking to walls/ledges, add a Physics Material to the Capsule Collider that has 0 friction

Kat, and the provided script running on an NPC (with Kat's animations :P ).


(This is for Humanoid Rigs and uses the built-in IK solution)

Foot IK

For the feet to adapt to the floor you have to set the Position, Rotation, and Weight of the IK Overrides.

Find the Position and Rotation by raycasting down from the Feet bones. And using the hit.point for the position, and rotating with the hit.normal

leftFoot = anim.GetBoneTransform(HumanBodyBones.LeftFoot);
if (Physics.Raycast(leftFoot, -Vector3.up out hit, 3))
targetPosition = hit.point;

Quaternion rot = Quaternion.LookRotation(transform.forward);    

targetRotation = Quaternion.FromToRotation (Vector3.up, hit.normal) * rot;        

Then set the IKPosition and IKRotation

anim.SetIKPosition(AvatarIKGoal.LeftFoot, targetPosition);
 anim.SetIKRotation(AvatarIKGoal.LeftFoot, targetRotation);

Set the weights for position and rotation, based on Animation Curves

 anim.SetIKPositionWeight(AvatarIKGoal.LeftFoot, leftFoot_Weight);
 anim.SetIKRotationWeight(AvatarIKGoal.LeftFoot,  leftFoot_Weight );

Then do the same for the right foot

The foot floats on the walking animation.

Head IK

Compared to the others, setting up Head IK is fairly straighforward. 


A very simple way to blend is to grab the distance between the lookAtThis position and the Head bone. Invert the distance to get a nice transition

float distance = Vector3.Distance(anim.GetBoneTransform(HumanBodyBones.Head).position, lookAtThis.position);
anim.SetLookAtWeight(2-  distance , 1-  distance  );

The second float in SetLookAtWeight is the body moving in addition to the head.

Hand IK

Similar to the Foot IK part, this time raycasting from the Shoulders (you can of course use other parts, this worked for Kat)

You should blend based on a float in your animation again, so it doesn't move arms when you're in full body animations, but for now the script just blends based on distance like for the Head IK.

IK Script with comments : PasteBin Link
Just drop on the same object as your Animator. Set a "LookAtThis" transform in the inspector to play with that part

Links that really helped me:

Tim Dawson's Twitter thread about Character movement 

Sharp Accent's great video on Animator IK

Other Astro Kat Stuff:

I finally updated Bot-Friends model and now he has an eyelid for those moments that require a sarcastic look :D

UI for shops is done but no art is attached yet

UI for items/ inventory/ equipment etc have have been updated with a better setup, better scaling, waaaay more performant :)

Hand IK!

Better weapon system on it's way too.

Thanks for reading!