Been a while since I posted on here! Seems like keeping up regular blogging is something I need to work on.
Recently, I’ve been working on an exporter tool for UE4. When I was working at Five Pixels, we had a few issues with artists being a little forgetful or being used to different engines, which led to some import problems and crashes that were time consuming and annoying. I wanted to create something that would alleviate issues like this, whilst also creating a tool that is probably pretty fundamental for my tech art education!
The most important bits of functionality for this tool were using the correct FBX export settings for UE4, and moving the object to the origin. The placement of the object was one of our largest issues with importing at Five Pixels, as it was easy to forget, especially if you work with multiple assets in one maya file, and failing to correct it made level propping a nightmare – having your pivot miles from your object is not cool!
Export settings were a pretty easy one – I just grabbed the recommended settings from the UE4 Documentation (which is fantastically written – great resource for UE4 devs, if you’re not using it already). These settings turn on use of smoothing groups and smooth mesh, so you don’t lose any of that nice normals work. Most people will also turn on triangulate, but I’ve made this optional. There are three ways to triangulate a mesh for UE4; manually, on export and on import, and the topology of the model is going to determine which to use. Triangulating on export is generally the easiest method with the best results, so that is my default option.
The other option that the user is given is for a custom file path. Leaving this unticked will create the file with the same name and in the same place as the maya file. I was reluctant to include this option at first, as the idea of keeping a ridgid file structure is pretty appealing to me, but talking to others about their file structures reveled that a fair few people like to keep a separate folder for final exports.
On export, the tool moves the model to the origin, erases the history, and then undos these two actions. This is so that no data is lost from the maya file, and so that users are not inconvenienced by having to move their model back where they want it.
This is the very basic design – there are lots of other possibilities, like optional dummy nodes, generating collision meshes or working with material exports, but for now I’m keeping things simple.
I learned two very interesting bits of maya python with this script. These were use of mel commands and use of chunks in undo.
Accessing FBX settings seemed to be quite difficult with python, but a simple task in MEL, so I imported maya.mel and used the eval command to have my line evaluated in MEL and then converted to a python datatype.
maya.mel.eval("FBXExportSmoothingGroups -v true;") maya.mel.eval("FBXExportSmoothMesh -v true;")
Using undo chunks made reverting erasing the history and moving the object to 0,0,0 very easy. I opened the chunk, performed some actions and then closed it. Everything inside of the chunk then acted as one undo step – a slightly more elegant solution than undo-ing five times.
cmds.undoInfo(openChunk = True) pivot_to_origin() maya.mel.eval("FBXExportSmoothingGroups -v true;") maya.mel.eval("FBXExportSmoothMesh -v true;") cmds.file(fbx_path, force=True, es=True, type="FBX export") cmds.delete(constructionHistory = True) cmds.undoInfo(closeChunk=True) cmds.undo()
Structure was by far the most difficult part of this script. I’m still making changes to this, as my current solution is – for lack for a better word – totally gross, and may not work correctly when distributed.
The current issue is that in order to make the text box update with the new file name that the user chooses, the textfield has to be in the browse function. If its left in the UI function, it only updates when the window is first made. This doesn’t work however, as once it is in the browse function, the field being edited either needs to exist in the function, or be global. Another issue to add to this is that the parent window needs to exist in the same scope as the field. Right now, my whole UI has been moved into the global space, which is beyond bad. It works, but it is such bad practice and really limits how this tool can be edited.
But everything else is working well, so once this is fixed I can think about adding more functionality, support for skinned meshes and maybe other engine support.