Creating a Quadruped Character Controller in Unity (with Malber's Animal Controller)

 For Pocket Moon's new in-development title, The Attestation of Sköll, I've been working on the gameplay-technical side of things, starting with interactions, dialogue, the camera system, and primarily the character controller.

The titular character Sköll, the wolf of Norse mythos, is a quadruped which has meant that I can't use my go-to imitation-Source-Engine controller, which is designed not only for first-person games but for bipedal characters; the important difference between quadrupeds and bipeds when it comes to controllers is that a quadruped is not rotationally invariant along its vertical axis: a typical controller with a vertical capsule for collision checking can be rotated safely along the Y-axis without really changing the space the collider occupies, but if you were to turn that collider on its side, suddenly a simple yaw rotation can put the collision volume inside of another object.

To solve quadruped collision and control, I started with a prototype that used two spheres to represent the front and rear of the animal. The front would attempt to move and orient toward the target direction, while the rear segment followed and tried to orient toward the front. This somewhat solved the problem of rotating in a confined space, by allowing the segments to solve themselves into a free space, but this presented the issue of the two segments potentially ending up overlapping too much, which would look broken if used to inform the character model.


After a lot of trial and error with this method, I decided on using a tool specifically for animal character controllers, developed by Malbers. Although there's a lot of tinkering and even modifying the tool's own code, it handles most of the complicated things like collision and ground alignment, and meant I could start working with root-motion animations for our character.

Root motion refers to using a rig's root bone to move the entire character, by translating the bone's per-frame translation into a translation on the entire object. This method of locomotion is difficult to control more precisely from a gameplay perspective (movement techniques, physics-driven/rigidbody-like motion) but results in far smoother, artistically-tuned movement with minimal, if any, foot-sliding.

 

To select animations and controller behaviours, the Animal Controller plugin uses a state machine to represent whether the character is idle, locomoting, jumping, etc. The transitions between these states can be dependent on inputs or on other conditional checks such as for the fall and ledge-climb states.

With states for idle and locomotion set up as per the plugins easy to follow guide, the bulk of the work to get the character moving was with animations for standing and walking. Walking animations can have separate speeds that can be blended between or selected outright, as well as turning animations that match the step phasing and general motion of each other, allowing a blend tree to govern how the character makes turns while walking.

Basic Locomotion


Creating these animations in the first place was the biggest challenge, as I'd previously not worked with root motion before and set myself the target of eliminating foot sliding entirely; I tried a few solutions regarding the root bone, one of which being the feet (and respective IK bones) unparented from the root bone which allowed for the root to move without causing any motion in the feet, eliminating sliding. The problem with this approach was that when you wanted the feet to follow the rest of the body, such as when the feet are picked up between steps, they must be moved manually.
I settled eventually on having the feet IK bones parented to the root, and using an auxiliary bone, parented to nothing, for each that the feet can copy the location of via a bone constraint:

The "foot lock" auxiliary bones: once a foot is placed on the ground, it enables the constraint until the foot is later lifted, so that any root bone motion has no effect.

To create a smooth and convincing turning animation, which could be blended with the forward walking animations and idle animations to create a range of motions, I initially tried keying the root motion manually which looked too linear and jagged for the curving trajectory I was hoping to achieve. I experimented with more driven motion, and settled on using a follow curve constraint with a turning circle in the form of a Blender curve. Once the root motion was done, I copied to foot and spine motion from the forward walk animation and adjusted each foot to properly walk the character along the curved path.

Jumping & Climbing

Similarly to the locomotion solution, I used root motion to power the jump and ledge climbing systems. Malbers' controller has an interesting approach to jumping, allowing you to define a full jump animation that includes a landing portion, and checking whether it should complete said animation or transition to the fall state at the apex of a jump. Aside from tweaking a few parameters to align the jump properly to the ground, jumping was by far the simplest part of this controller setup to create.
Ledge climbing, on the other hand, is a lot more complicated - as is ledge-dropping. To create the several animations for climbing ledges of different heights, I reused the foot lock system and created dummy geometry in Blender (literally just a box) to block out the climbing sequences. The controller plugin allows for these "heights" to be selected based on a raycast that determines whether there's a ledge ahead and what height it's at relative to the character, so I created three climb profiles that use each of the three (low, medium, high) animations.

Without doing some in-engine IK, it would be impossible to have a perfectly convincing climb animation on a variable-height ledge, as each animation was created for a specific ledge, which unfortunately leads to the wolf's hind legs either clipping into or floating above the floor, as the forelegs are brought to level with the ledge itself by moving the entire character.




To activate the ledge climb state, the plugin has options for performing it automatically or when a particular key is pressed, although I had to add some modifications to get the particular behaviour I was after: I wanted shallow ledge climbs to be performed automatically, but only when the movement keys are actively being held to prevent latent motion from another ledge climb from activating itself again when another ledge is present.

To tidy up the few remaining issues with animation blending, I modified the plugin again to reset the animator parameters used for the locomotion tree when climbing - this stops ensures when the state transitions from climb to locomotion, it doesn't snap to the walking angle or speed it was before the climb.


Although I've yet to add other walk speeds and stances, the result is workable for now until we get the rest of the game fleshed out.

Comments

Popular Posts