Friends, food, and flourishing

MalberS magic: locomotion

Earlier, I used the MalberS Animal Controller to make a corgi run through randomly chosen idle animations. Now let’s make the doggo walk around. This post is based on a MalberS tutorial.

Read the earlier post first, if you want this one to make sense.

Deer me!

Let’s start by checking out a deer MalberS already set up. Here’s the Animal component:

Deer states

Locomotion is the one we’re interested in this time. AC expects an animation controller set up, so it can manage the locomitiony stuff.

Here’s the deer’s animation controller:

Deer animation controller

On the left are parameters animal controller (AC) uses to bend the deer to its will. Your animation controller needs them, too.

On the right, you can see there are substate machines for different states. In the previous post, we made a substate machine for idling. You can see another one for locomotion.

Inside Locomotion, there are two blend trees.

Two blend trees

We’ll only make the location one, for moving around.

Blend trees are way cool. They let you combine animations to make a composite effect.

How blend trees work (maybe)

To see how that works, we first need to understand what animations are doing. Here’s the deer’s 3D model:

Deer model

Here are the bones inside the model:

Deer bones

A “bone” is a vectorish thing. Changing the vector changes the model part connected to it.

For example, to make a deer walk, you rotate its front left upper leg bone on its X axis, where it attaches to the hip. That lifts the whole leg off the ground. You rotate the knee bone as well. And so on, with all the legs, until the model looks like it’s walking.

Coordinating all the bones so movement looks natural is difficult. Here’s part of a walking animation for the deer:

Walking animation

Lots of bones, lots of coordinated movement. Each diamond is an operation on a bone, like “rotate the left foot 12 degrees on the X axis.”

OK, that’s a walk animation. A turn-left animation will have its own operations, like “rotate the left foot 16 degrees on the Y axis.”

When you blend animations, you combine the operations on their bones. To get walking while turning left, an operation might be “rotate the left foot 12 degrees on the X axis and 16 degrees on the Y axis.”

A blend tree tells Unity how to combine multiple animations. You can combine them in many ways. For example, if you want to turn left slowly while walking, you have more of the walking operations and less of the turn operations. Or you can have the deer walk backwards, by running the steps backwards.

Sometimes combining works, sometimes not. MalberS’ animals have many animations, for all sorts of things. For example, walking to the right in a single animation. It looks better than combining walking and turning right. The single animation has spine and head movements that look more natural than the combination of walking and turning.

Movement blend trees

When the deer is moving, it’s on the ground, moving in two dimensions. It uses a type of blend tree that translates movement in those dimensions to particular animations. So if the deer is moving at a normalized speed of 1 in Z and 0 in X, play the walking forward animation. If the deer is moving at a speed of 2 in Z (running forward) and -1 in X (turning left), play a running-while-turning-left animation if you have one, or combine a running animation with a turning left animation.

So Unity is mapping movements on a plane to animations and animation blends.

The mapping is a 2D Cartesian blend tree, that’s particularly good for locomotion. As they say on the Beeb, other blend tree types are available.

Here’s part of the deer’s blend tree:

Deer blend tree

It uses horizontal and vertical values to control animations. You don’t see the values here, though. Click on the blend tree, the big node on the left, and the inspector shows you:

Cartesian blend tree

Here, Vertical is actually Z in world coordinates. The standard 2D Cartesian system uses X for horizontal and Y for vertical. That’s where the blend tree’s dimension names come from.

The table says:

  • When X (left/right) is 0 and Y (forward/back) is 1, play the DWalk animation at a speed of 1.
  • When X is -1 and Y is 1, play walk left.
  • When X is 1 and Y is 1, play walk right.

There are 20 entries in the table. MalberS gives us so many animations!

OK, time for…

Moving the dog, dawg

Change the Animator, so its Update Mode is Animate Physics, and its Culling Mode is Always Animate. I think you have to do both, but I’m not sure.

First, we need to add a locomotion state in the Animal component.

Add locomotion

The id of the state is 1, and its tag is Locomotion. We’ll need them later. (This is similar to adding the Idle state, as we did before.)

Locomotion added

In the animation controller, add a Locomotion substate thingy. Make a transition from Any State, with the conditions StateOn and State = 1. Similar to the Idle one we made before.

Locomotion substate machine

In the substate machine, add a blend tree. (This is different from what we did with idle.) Note the tag.

Add blend tree

Now to set up the blend tree. Here’s what I used:

Locomotion blend tree

The blend tree type is the Cartesian freeform thing. I added four animations for the corgi: idle, walk forward, walk left, and walk right. They’re controlled by Horizontal and Vertical values. Horizontal is for left/right, Vertical for forward/back.

The values should make sense. For example, if Horizontal is -1 and Vertical is 1, walk left and forward. If we can set values for Horizontal and Vertical, the right animation should get chosen.

Clearly, I’m only making the doggo walk for now. Trotting and running come later.

One problem I had was Carl Corgi (let’s go with the name Carl) would move one step, and stop. I noticed the deer animations were set to loop, but Carl’s weren’t. So I changed them.

Loop time

I had to hit Edit first, to make the animations editable.

OK, we have a locomotion state, which should work, if we set values for Horizontal and Vertical used by the blend tree. The animator controller has Horizontal and Vertical parameters.

Horizontal and vertical parameters

How to control them? We could write a script, or use MalberS components. Hmm. Let’s MalberS it.

Which MalberS component to use? We could control Carl with an input component. Press A and Carl walks. That’s what I did initially, when testing.

However, in the game I want Carl for, he’ll be an NPC, controlled by AI of some sort. MalberS gives us tools for that.

A note on root motion

The corgi came in three versions:

  • Clear: no animations.
  • Root motion (RM): root motion animations, where the corgi’s position change is baked into the animations.
  • In-place (IP): when the animation is running, the position of the corgi doesn’t change.

With RM, playing a forward walk animation moves the corgi game object (GO) forward by changing its transform’s Z. You don’t need your own code to change the position.

Playing IP animations doesn’t change the GO’s transform. You need to change its Z if you want it to move.

When I made Carl, I used the RM animations that came with the prefab. No problem.

Later, I repeated the process for a retriever called Reilly. I used Reilly’s IP animations. He walked in-place, as you might expect.

To get him moving, I had to change his Ground speed set. Speed sets let you set speeds for walking, swimming, flying, etc. They’re explored more in another post.

The Animal component makes a Ground speed set for you. I set Reilly’s Root Motion Pos and Rot to zero in the General tab.

No root motion

In the Speeds tab, in the Walk section, I set position and rotation to 1.

Walk speeds

Why 1? These are values used in the Cartesian blend:

Locomotion blend tree

When I tried it, the animation would stop before the Reilly’s position stopped changing. It looked like Reilly was skating along the ground for a bit before stopping.

To fix it, I changed the Lerp value for the position to zero. That’s the L here:

Walk speeds

I don’t know if that’s the best way to do it, but it worked. I might change the L for rotation as well, if it causes issues. It doesn’t seem to, so far.

(Later, I changed Position from 1 to 0.9. It gave a better-looking walk.)

Now back to your regularly scheduled post.

Carl wanders

To KISS, let’s make a few waypoints, and have Carl walk between them. I made some waypoints:

Waypoints

Waypoints

MalberS has a waypoint component. You can drop it on an MT GO, or use the WayPoint prefab MalberS provides.

Waypoint

When Carl reaches this waypoint, he waits from 1 to 5 seconds, then chooses a random destination in the Next Way Points list.

OK, we’ve got the waypoints, but how does AC use them? We’ve got the MalberS AI control component for that. It’s placed on a child of Carl’s GameObject:

Corgi kids

AFAIK, it just controls waypoint and wandering behavior. There’s another component, AI brain, for other uses. I think. I’m not sure yet.

Here’s Carl’s AI control:

AI control

The initial target waypoint is given. When Carl reaches it, he does whatever the waypoint object says. In this case, choose another random waypoint from a list:

Waypoint

The AI control component has a reference to a nav mesh agent. Makes sense. Rather than reimplementing navigation, MalberS AI control tells Unity’s normal nav system what to do.

You need to make a nav mesh, of course, for the agent to use. Make sure you have some static objects, and bake the mesh.

A curious thing, though. I created a Corgi agent type…

Corgi agent type

… and used it in the nav mesh agent:

Agent type set

It didn’t work. I looked at the deer’s settings (the one configured by MalberS). It used the humanoid settings. I changed the corgi to humanoid, and all was hunky-dory. I don’t know if humanoid is required, but it works.

Watch me walk, I can waaaaaalk and waaaaalk

I wanted to watch Carl wander about. For that, I used Cinemachine (CM). Add a CM brain to the main camera. I didn’t have to change any settings. The brain links CM virtual cameras to the real(ish) Unity camera.

Next, I created an MT GO, and added a CM virtual camera. I set the Look At field, Body to Do Nothing, and Aim to Composer.

Cinemachine settings

Off Carl went, and the camera followed him, as expected.

Carl

One thing I didn’t like was how Carl turned before he started walking to a new point. If the turn angle was largish, above 30 degrees or so, the rotation was unrealistic. He’d spin on the Y axis, without turning with his legs or spine.

The redoubtable MalberS thought of that. There are AC settings that help, under the General tab:

Turning parameters

I messed around with the numbers, until I got settings that worked for Carl. Like so much in Unity, I’m not sure what they do, but they work.

I’ve struggled with animal rotation before, and never came up with a way to do it well enough. MalberS makes me happy.

Victory, not Sovengarde!

Weehoo! A nice wandering doggo 🐶. Maybe I’ll work on trotting and running next.

Leave a Reply

Your email address will not be published. Required fields are marked *

css.php