Here are Will’s five awesome tips for animator controllers. A key point to keep in mind: build animator controllers for your characters like you would a script: build them so they’re efficient to reuse, extend, support and debug, all the way through the development cycle.
All of the screens are from animation for the character Henry in Firewatch.

1Hide complexity in blend trees

Blend trees are good for hiding complexity. A blend tree doesn’t have state; it doesn’t call back out into code. It simply blends between the different clips based on the parameters you define.

The significance of this is that you can iterate on blend trees without worrying about breaking the rest of your game. You can hide a complex web of states, and prevent bugs down the road, because you can’t tie behaviour to most of the animations in a blend tree.

It looks complex, but this locomotion blend tree actually helped to keep things straight-forward.

2When you think “layers”, think: “a script class”

It helps to think of layers as a rough analogy to a class in a script. You want everything in a layer to serve both the same logical and behavioural function. This is because every layer controls what other layers it overrides, whether or not it affects certain bones, whether that layer is additive, and so on.

All of the states for Henry’s left hand. Each layer has a purpose, and a clear hierarchy. It makes it easy to control and easy to find state.

3Reuse patterns

Reusable, logical patterns in state and sub-state machines speed up development, allow multiple people to make similar content, make debugging easier and can in fact reduce bugs overall.

A few patterns that are good for structuring your layers:

  • The hub and spoke: this pattern makes it easy to debug, because you can see clearly the transitions go out and come back into the empty state. Every spoke of the hub should reset any state it touches. Spokes are good candidates for making into sub-state machines using the patterns below.

    A hub and spoke pattern used to animate Henry’s right arm.
  • The shared entering/shared exiting pattern: by grouping states into a pattern of ‘intro’ - ‘execution / loop’ - ‘outro’ you can cleanly attach any animation events or state machine behaviors to the ‘intro’ and ‘outro’ states. Much like a blend tree, you can then iterate and change the inner ‘execution / loop’ states without worrying about breaking your game.

    Entry to Exit: All of the states for Henry’s right hand to hold a book; more substates hiding details underneath
  • The critical-section and settle pattern: for interruptible animations, especially player input driven animations, break your clip into two parts. First, a critical-section that contains all state changes, effects, damage, etc., that must always play to completion. Second, a settle animation that looks good getting you back to idle and that can be interrupted by new input.

    Once your animations are working and looking like you want them to, you need to feed back the state of your animators into the state of your game. A couple of good points when doing that.

4Don’t write complex code inside of state machine behaviors

State machine behaviors are bits of code that you can attach to any animation state. You use them to tie behaviour directly to the state of the animator itself.

Avoid writing complex gameplay code inside of them because it can get difficult to track down where your changes in the state are coming from. If you are using state machine behavior to drive game play code, use a messaging system; talk to a manager, or fire off parameters at a higher level.

Finally, my favorite state machine behavior: Debug.break. It’s the most useful state machine behaviour; you can attach anywhere in your animation setup, and you’ll have a breakpoint, similar to that of a visual scripting system.

5Use state machine behavior to ensure an animation event always fires

Animation events tie a specific moment of your animation clip to a specific change of state in your game; they can be used to set off things like visual and sound effects. However, if you transition out of a clip before it has fired, then it will never fire. A way to solve this is to add a state machine behavior that ensures the event always fires when a specific point in time is reached, no matter what else happens, or doesn’t happen, in the game.