Setting up the character animator for Mighty Action Heroes

In this article, I would like to share the processes involved in setting up the character animator for Mighty Action Heroes and the improvements we made along the way.

To kick off the task, we started having weekly animation syncs attended by at least one representative from art, engineering, and design. These meetings were important as we would discuss details such as the animation states needed and how animations should be scaled to data when required, ensuring that all disciplines were aware of and aligned on how the animator would be implemented.

The first state we began working on was the character’s movement state. Our initial approach was to use a 2D blend tree. We would have 4 movement animation clips — move forward, move backward, strafe left, strafe right, and let diagonal movement animations be resolved by the blend tree. We then added mirrored animations to improve the diagonal blends as suggested by most online tutorials. However, when this was tested in a play session, we received feedback that the blended diagonal move animations still looked weird.

Diagonal movement animations from blending need further improvement

In reaction to the feedback, we attempted to play the movement animations we have as follows:

Segmented movement animation

Without blending, there is a noticeable snap when the movement animation changes. Instead of setting the target vertical and horizontal movement parameters directly, I made a change to interpolate the values so that the transition looks better. This is what we currently have implemented in the game:

Segmented movement animation with smoothing

Once the main base layer states were implemented, we started adding character actions in a new layer with an upper body mask applied to it. The character actions have different substates and are scaled differently based on requirements from the designers. The attack action is split into the following substates — attack start, attack loop, attack end. The attack start substate is for the animation that would play when the attack gets triggered by player input and before the actual attack happens. This is scaled to any initial attack delay set by the designers. The attack loop substate is for the animation that plays when the actual attack happens. For automatic weapons that continue to fire while the attack button is held down, this substate has a speed multiplier that allows it to scale to the rate of fire of the weapon. The attack end substate would be for the animation that plays when the player needs to recover from firing.

Attack animation playing at different speeds scaled to weapon’s rate of fire

The reload animation on the other hand, does not use a speed multiplier for scaling. Instead, the animation plays at the original animated speed and continues looping for the reload duration defined by the designers. It would be interrupted by a transition to the next upper body state once the reload duration is up.

Reload animation plays at the same speed but continues to loop for different reload durations

Something I learnt from a previous workplace and continue to practice every time I set up character animators is to use animator override controllers. The base animator controller would have empty clips assigned to each state, and the actual animation clips to be played would be assigned in the animator override controller. In most cases, characters share the same animator states, transitions and parameters, but not necessarily the same set of animation clips. The main advantage of using animator override controllers is that it becomes easy to reassign the controller and animation clips at runtime. In Mighty Action Heroes, this is done when we swap weapons since one-handed and two-handed weapons have different animations for the same state.

Different move animations for one-handed and two-handed weapons

An improvement I made when working on the character animator this time was to write a tool to generate scripts with the required data from the character animator. I caught myself repeatedly defining the variables I needed from the character animator in script, and it then occurred to me that I could automate this process.

To ensure that the generated scripts would always be up to date with the latest version of the character animator, I added unit tests to compare the animator data against the generated script fields.

Unit test fails after I added a new parameter without regenerating the scripts

The implemented movement animation works for now, but a polish task for it would be to have the upper and lower body rotating separately so that the lower body can match the movement direction better. I spent a self-improvement Wednesday afternoon doing some R&D on this. There wasn’t any discussions on possible implementation methods that I could find on the web, so I tried asking ChatGPT and this was its reply:

The angle at which you start rotating the lower body depends on the specific requirements and constraints of your game or project. There is no fixed angle that applies to all situations.

Typically, the lower body starts rotating when the player’s movement direction deviates significantly from the direction they are facing. The threshold angle can be determined based on the game’s camera perspective, the character’s field of view, and the desired level of realism. It is a matter of balancing aesthetics and functionality.

While this response didn’t contain any suggestions for me to get started, it helped me brainstorm for a solution. I decided to start working on what I could first — rotate the lower body to face the move direction and rotate the upper body to face the crosshair.

Separating character’s upper and lower body rotation (first pass)

The character rotates in a strange way, but with this it was easier to see what needed to be fixed. The backward movement animation should play when the unsigned angle between the look direction and move direction is more than 90 degrees.

Separating character’s upper and lower body rotation (second pass)

The other fix would be to play the strafe animation when the movement direction is almost perpendicular to the look direction. As strafing is set when the player’s input direction for movement is perpendicular to the character’s forward, the character’s lower body would need to face the look direction.

Movement blend tree

Separating character’s upper and lower body rotation (third pass)

It was fun working on the character animator and I’m glad I could share what I’ve learnt from it here. If you liked this article, do consider dropping some claps and following Mighty Bear Games on Medium!

Setting up the character animator for Mighty Action Heroes was originally published in Mighty Bear Games on Medium, where people are continuing the conversation by highlighting and responding to this story.