Maya to Unity Animation Pipeline

This is a high-level overview of how our Maya-to-Unity animation pipeline works at Big Fat Alien.



Unity already has a tight integration with Maya, but there are still many different ways to approach the problem of generating skeletal animation for Unity.

Requirements

1-click exporting from Maya

1-file per animation, no specifying frame-ranges

fast, easy-to-animate, character rigs

easy to modify rigs, and automatic-updates to animations 100% procedural rigging (no time for manual rigging) Simplicity. We can’t afford to spend time debugging complex things.

Pipeline Overview

This is how I get animations from Maya into Unity:

Notice the complete lack of branching. This is nice linear pipeline.

1.a. Modular Procedural Rigging

The pipeline starts with our Python-based procedural rigging system. I will cover this system in subsequent blog posts, but suffice to say its comprised of a set of python modules which roughly correspond to various body parts.

We have modules for legs, arms, heads and arbitrary FK-chains.



Each module sub-classes a base ‘RigModule’ class which supplies functions for building the rig and then connecting it to other modules via publicly advertised ‘hooks’ and ‘handles’.



A typical animation rig might be comprised of 5-10 modules which control different joints in the skeleton file.

1.b. Skinned Mesh (.ma)

This is the final character which will play animations in Unity. Unlike the raw animation/rigging files, this one lives in the Unity asset folder and is built by Unity.



It is a very simple Maya scene that contains only 3 elements:

Mesh: A single combined character mesh (1 mesh = 1 draw call)

Skeleton: A plain FK skeleton, with a consistent structure starting with a root joint at the origin (which is used to move the character from code).

Skinning Data: a skinCluster deformer with tuned weights

2. Rig Definition (.py)

This is a custom python module specific to each character. It’s job is to apply rig modules to a skeleton file to generate a control rig which an animator can use.



It will:

Add modules for each body part: self.addModule(leg) Define what joints belong to each module: leg.joints = [joints]

Specify how each module connects to other modules: self.connect(leg,hips)

Specify a skeleton file to operate on: self.skeleton = “c:/dragon.ma”

The base RigDefinition class has a build function which will run the build functions for all of the modules and then connect all the hooks/handles to parent the control rig correctly (ie. Neck-hook attaches to Spine-handle, Leg-hook attaches to Hips-handle etc).





The build function will save the resulting animation rig file to disk (#3).

3. Animation Rig (.ma)

When the rig definition is built (ie by running, dragon.build() ) the output is a Maya file that is ready to animate. It includes:

A copy of the Skeleton file (with intact FK skeleton, constrained to the control rig) Controller curves for easy manipulation of the puppet Advanced control methods (IK, auto-twisting/stretching, look-at, IK/FK blending etc)

4. Animation Scene (.ma)

The Anim Rig from step 3 is referenced into a new animation scene for each animation clip (ie, dragon_run.ma, dragon_bite.ma etc). Using Maya’s file referencing feature is a huge time savings. By referencing the rig, we can propagate model and rig changes through the whole pipeline automatically.



When the model/rig needs modified, we go back to the Skeleton file and make the change there. Then re-run the “dragon.build()” procedure to auto-generate new “DragonRig.ma” files. Now when we open our animation scenes, they will automatically have the latest dragon rig.



5. Exported Animation (.ma)

We have a 1-click Python routine which is run on an animation scene. The output is an animation maya file which is consumed by Unity and turned into an animation clip. One animation scene file per clip.

The export routine simply bakes all animation from the control rig into the FK skeleton. It then saves only the skeleton with the FK animation data to a separate Maya file which is stored in the appropriate Unity asset folder.



Note on FBX: we use Maya ASCII format instead of FBX. While this may incur an additional build-time cost, I find it simplifies the export pipeline greatly by just letting Unity deal with the conversion internally (Unity uses the FBX SDK to import Maya files and automatically selects the correct FBX conversion settings for you).

We have a batch export tool which can be used to auto-update animations when a model/skeleton is changed. Doing a full batch export will rebuild the animation rig, opens all the animation files (using the newly generated rig) and re-runs the export routine on each one.

All of this can be structured into a single click which propagates any model/rig change from the Skeleton file, to the animation rig, to all the animation scenes and finally into Unity where the updated clips are automatically integrated into the game.

All of this is facilitated by a simple folder structure where each animation rig lives next to all of it’s animation scenes. This is outside of the Unity asset folder.

Note on Asset Folder: Only the exported Maya animation files live in the Unity asset folder. This is to keep a clear separation between final baked-out game content and the raw assets used to author it. It also prevents Unity from building redundant maya files as Unity will automatically build any and all .ma/.mb files stored within the project’s asset directory. Therefore, we only put Maya files in the Unity asset folder if they are intended to be used by Mecanim.

Final Thoughts

This animation pipeline has been production proven.



It meets all of the requirements outlined at the start of this post and it’s proven to be very easy to use and modify. Python is the perfect level of abstraction for an animation pipeline.



A modular procedural rigging system, in conjunction with Maya’s referencing system and a simple batch exporter allow for rapidly produced, high-quality animations.



Ultimately, I wanted to concentrate on the actual animation and this pipeline allows us to do that. I’ve pasted an run-cycle below that was built using this pipeline. It’s a character from our upcoming game which we will be announcing soon…





via GIPHY