A Better Maya to Unity Workflow

April 7th, 2014

In the past, I’ve implemented tools and fixes to Unity’s import pipeline of native Maya files by manually modifying the FBXMayaExport.mel script. Unfortunately, these types of modifications are difficult to maintain. For one, they need to be redone every time the Unity installation is upgraded. Second, the files are buried in obscure places that require administrative privileges to modify them. It would be ideal if changes could be made in one place, one time, in a way that supported more modular design. So, I finally decided to take the time to sit down and tackle this problem.
Read the rest of this entry »

Help—My Blendshapes Aren’t Working!

January 13th, 2014

Every now and then, I get emails, comments, tweets, or some other communication asking me for help getting blend shapes into Unity with my (now quite old) Maya Extensions package. It’s understandable because the tool I put out was very fragile for a lot of reasons (many my own fault), and I simply haven’t had the resources to finish up and distribute an update. However, because Unity 4.3 now natively supports blend shapes, I have been advising everyone who only needs blend shapes to simply update to 4.3.

Unfortunately, due to errors in Autodesk’s FBX SDK, you can run into a bunch of problems in Unity if you export your models with anything newer than FBX version 2011 (e.g., blend shape data importing incorrectly, animation curves for blend shapes not importing). Although you can of course work around this problem by manually exporting your models as FBX and selecting the appropriate version, many people opting to use native Maya files (.mb or .ma) have instead begrudgingly used older versions of Maya. (While I have no personal experience with it, I’ve been told it’s a similar situation for Max users.)

Fortunately, there’s a fix you can implement to work in your latest version which at least resolves all problems I have encountered. Namely, you can make the following modifications to the FBXMayaExport.mel script in your Unity.

  • Mac: /Applications/Unity/Unity.app/Contents/Tools/FBXMayaExport.mel
  • Windows: C:\Program Files (x86)\Unity\Editor\Data\Tools\FBXMayaExport.mel

First, lines 43-48 read like this:

if (getApplicationVersionAsFloat() >= 2013)
{
    print "Setting FBX version to FBX201200.\n";
    // Ensure we are using a version of FBX that Unity can currently support
    FBXExportFileVersion FBX201200; 
}

They should be this:

if (getApplicationVersionAsFloat() >= 2012)
{
    print "Setting FBX version to FBX201100.\n";
    // Ensure we are using a version of FBX that Unity can currently support
    // and for which blend shape animation curves are not broken
    FBXExportFileVersion -v FBX201100; // NOTE USE OF -v FLAG
}

Second, line 96 has this command:

FBXExportHardEdges -v $exportNormals;

My understanding is that the only purpose of this command is to force physical separation of vertices with multiple normals for old versions of MotionBuilder that could not support multiple normals for a single vertex (see here and here). As such, I have encountered no adverse effects from changing it to the following:

FBXExportHardEdges -v false;

Hopefully these changes work for you, too! Let me know in the comments if you experience different results.

Reenabling Spotlight Menu Search in Maya 2014

October 11th, 2013

If you are primarily an OS X user, you may rely on the keyboard shortcut for accessing the Help menu’s search field (Cmd-Shift-?). As someone who is accustomed to doing lots of (lazy, IDE-assisted) typing, it is by far the fastest way for me to get to menu items in all Mac apps, without setting up all sorts of exotic keyboard shortcuts that put my hands through gymnastic routines. It also has the benefit that I never need to learn menu structures or navigate to deep items.

As a testament to how much time I’ve been spending in Maya lately, I unfortunately only noticed today that this feature no longer exists in Maya 2014! Sean Donnelly at Autodesk helpfully explained the problem. In short, because the operating system automatically takes control of menus called “Help”, they were unable to get some of the new UI features to work with it (e.g., the super helpful “What’s New” highlighting scheme they’ve added). Consequently, the help menu label in Maya is now “Help “. If you want to get the spotlight search back, there are a number of ways you can approach the problem, but I found it easiest to add a dummy menu with the following simple snippet in my userSetup.py:

import sys
import maya.cmds as cmds
import maya.mel as mel
import maya.utils as utils
if mel.eval('getApplicationVersionAsFloat') >= 2014 and sys.platform == 'darwin':
    deferred_command = \
    """
cmds.menu(
    'SpotlightHelpMenu',
    parent=mel.eval('$gMainWindow = $gMainWindow;'),
    tearOff=False,
    label='Help',
    familyImage='menuIconHelp.png'
)
    """
utils.executeDeferred(deferred_command)

Feeling Biped-Curious?

July 21st, 2013

My Biped tool is the Summer Daily Deal in the Unity Asset Store, today only. Grab it at 50% off and try it out!

Null Components and You

November 24th, 2012

Do you use the null coalescing operator?? If so, be careful about using it with properties of MonoBehaviour that return a component. For example, if you have an object with no rigidbody attached, the following example will not in fact add a rigidbody:

Rigidbody rb = rigidbody ?? gameObject.AddComponent<Rigidbody>();

Why? For some reason, these built-in properties (such as rigidbody, collider, and so on), actual return an object of the appropriate type that evaluates to null, rather than an actual null reference, even when the component does not exist. For example, on an object with no rigidbody, this line will log true:

Debug.Log(rigidbody.Equals(null));

On the other hand, this example will throw a NullReferenceException, as expected:

Rigidbody rb = GetComponent<Rigidbody>();
Debug.Log(rb.Equals(null));

As such, you can rewrite the first example in the following way and it should work:

Rigidbody rb = GetComponent<Rigidbody>() ?? gameObject.AddComponent<Rigidbody>();