Monday 11 January 2016

Importing rigs from Maya to Unity

I have been working at the games studio: Mojo Bones for a little over 2 months now. This is my first job in games and I have had to overcome a range of problems when importing rigs from Maya into Unity.

Here are some of the key problems I faced and resolved which I shall discuss in this post:
  • Hierarchy - Why Unity hates broken hierarchy and how to deal with it.
  • Scaling - stretchy squashy joints. Why this won't work out of the box and how to overcome it.
  • Naming conventions (naming clashes can cause problems whatever program you are in!)
  • Avatars - what they are, and how to set them up.
  • Exporting to an FBX - what to include, and what settings to set.
  • Humanoid setup with Mecanim.
  • Extra/Additional bones when using Mecanim (like wings, clothes, or in my case a backpack.)
  • Jittery Animation? Probably keyframe compression.

Hierarchy
The Fix:
If you are using a broken-hierarchy rig, follow these steps:
  1. Select all joints you want to be bound (or are already bound) to the skin in the initial broken hierarchy rig. 
  2. Duplicate them.
  3. Remove any constraints and connections. 
  4. Parent any broken sections ( eg: ribbon joints ) 
  5. Parent constraint each of the newly duplicated joints to their respective broken hierarchy rig counterparts. 
  6. Give them a suffix. ( eg: 'game_' )

The Explanation:
Mecanim hates broken hierarchy. That is the nub of it. If any part of your rig uses broken hierarchy (such as ribbons) Unity will spit it right back out.

You can follow the fix above and do this manually each time for every character OR you could save yourself potential hours and script it... OR you could save yourself even more time and use my script,
which you can download for free below.

AT_gameRigJnts.zip

Extract the download into your Maya scripts directory, and then run these three lines of code:

import gameRigJnts
from gameRigJnts import *

gameRigJnts.gameRigUI()


Scaling joints - squash and stretch 
The Fix:
You will need 2 rigs for this to work as mentioned in the hierarchy section of this post. When all game rig joints have been constrained to the broken hierarchy rig, you can now see that the scaling in the axis that points down the joints (in most cases the 'x' axis) works. Whilst this now squashes and stretches it does not retain mass.

Unfortunately you will need to effectively 'scrap' the conventional 'y' and 'z' stretch nodes/expressions and fake it with blendshapes instead. Blendshapes are fairly heavy on game engines, some do not support their use and you will never get an exact mathematical squash and stretch - but it will do the job.

The Explanation:
Turns out Unity hates scaling joints too. After scripting my own stretchy/squashy spine in Python and implementing it into a rig for Unity, I soon discovered that the deformations were not transferring over as they looked in the viewport for Maya as they did in Unity's animation inspector (viewport).

Annoyingly, I couldn't seem to find the issue immediately, as nothing seemed to be out of the ordinary and no warnings were flashing up upon import. However... after doing a bit of searching around on the internet, I discovered that Unity does not evalate scaling in the same way that Maya does. Infact, Maya seems to have it's own scaling algorithm built into it when it comes to scaling joints.



Naming Conventions
The Fix:
Make sure no two items are named the same when importing to Unity. Batch add prefixes if necessary with the 'prefix' tool in Maya.

The Explanation:
Naming conventions are something which cause problems all the time all over the place. Not only do naming conventions help keep everything tidy, organised and legible for when you or somebody else opens your scene up in 18 months time, it also prevents further problems down the line.

Naming conventions are ESPECIALLY important in rigging (although I'm sure every department would say that about their own part of the pipeline).
When you have 200+ joints in your rig, you need to be able to find something fast and efficiently. Naming may also help with specific scripts that you'll want to run in the future.

In this particular case, when I imported my first ever rig into Unity, I came across a problem with my naming conventions; name clashes.

The reason that I had a name clash was because I have 2 separate skeletons, one serving as a normal, broken hierarchy rig that I would usually use for vfx or cg film and the other - since Unity hates broken hierarchy - is a non-broken hierarchy rig. This serves as a 'dummy' or 'slave' rig that just follows the initial rig through parent constraints.

These two separate hierarchies (effectively duplicates of one another) each had the same names for the same bones - a bad practice whatever program you're in, but for Unity it was particularly bad for dealing with the Mecanim system and may have caused other errors down the line. Best just to avoid it at the outset.

Fortunately, this is a very quick and simple fix - just add a prefix to one of the skeletons, (eg: game_head_jnt, game_pelvis_jnt, etc.) Once this is done you are good to import to Unity.

4 comments:

  1. Thanks a lot for taking the time to write this out. The documentation on this is waaaay too sparse and this is really helpful info!

    ReplyDelete
    Replies
    1. Cheers dude! Glad you found it helpful, sorry that the post isn't fully complete yet - I will get round to finishing it soon. :)

      Delete
    2. I didn't mean to imply this page was sparse. I was hoping Unity's own documentation would explain more deeply which things worked or workarounds for things that didn't. I couldn't get your script working, but I wrote a crude workaround to fit my rig.

      import maya.cmds as mc

      #Skinning joints labled with an SK
      mc.select('*SK*')
      jntSK = mc.ls(sl=1)

      for x in jntSK:
      pCon = mc.duplicate(x, n = x.replace('SK', 'UNY'), po=1)
      mc.parentConstraint(x, pCon)

      mc.select('*UNY*')
      mc.group(n= 'UnityBones')

      #Manually parent bones into hierarchy

      Thanks again for the research!

      Delete
    3. Hahah not at all! Glad you found it useful. Ah damn, do you know what errors you got when you used my script? Would be good to go back and fix it for others.

      Delete