Introduction
I recently finished a Blender and Unreal Engine Python project that aims to streamline the process of exporting and setting up meshes in the engine. I've intended to share this insight for some time now. Not only to serve as a personal reminder for my next Python project but also to offer a learning opportunity for those interested in delving into this field. The python project mentioned in this post can be viewed here: Blender Unreal Workflow Python Tools
1. A tool that does everything?
I must admit that it's tempting to create an all-functional unicorn tool that could possibly result in end of all the game art and design challenges. Except, that doesn't exist. I struggled with this idea for sometime when coming up with a tool to eliminate all workflow woes of efficiently sending meshes from Blender to Unreal Engine. As a game artist, I've had my fair share of challenges when using Blender and Unreal Engine together, but after talking to several other artists, it seemed like the issue was larger than expected.
"I learned that being a Technical Artist entails finding the optimal solution that effectively balances user requirements with project needs."
I started out with the idea of making a "Validation and Export Tool" - two seemingly connected functions that cover a number of issues when dealing with creation and sharing of mesh from DCC application to engine. Common issues when exporting from Blender to Unreal Engine include - dissimilarity in scale units, axis orientation and origin point position when exporting from the former to the latter. This is in addition to common mesh issues, like bad topology, incorrectly facing normals, and overlapping vertices, that further create issues, often realized when brought in engine. This is just tip of the iceberg, the problem escalates very quickly when you're dealing with skeletal meshes or more complex setups.
As one can imagine, targeting multiple use cases can quickly turn chaotic. I was constantly trying to make something that performs both validation and export, but it could not do either of those efficiently without hindering the use of another. Somewhere down the line, I decided to break up my Blender set of tool into two components instead of one super tool - Mesh Validation and Mesh Export, each taking care of its own function. The latter one completes the loop in the form of an Unreal Engine Setup Tool that sets up the exported mesh in the engine. This compartmentalizing of similar but varying functions of the tool allowed me to focus on them independently.
Takeaway: Your tool does not need to solve all and every issue with the processes. Try to identify smaller components that can alleviate workflow issues. Also, this does not imply the tool should sacrifice usefulness for the sake of simplicity. If you find yourself working across several problems, targeting the challenges through different components of the tool could be worth exploring.
2. Artists and Designers are "Users"
I try to bring general UX design principles into practice as much as I can, reminding myself the need to keep meaningful user experience at the heart of the tools I develop. This implies keeping the tool user-friendly and accessible to those without technical knowledge too. The end-user in my case is an artist or designer without little or no knowledge of Python programming. While it is much easier for me to let the user type in a Python command in Unreal Engine console every time they wish to setup meshes and materials, it just doesn't make sense. I may not be making a tool to be used by everyone using Unreal Engine, however the artist using the tool is the end user, and they deserve simple and intuitive experiences.
Is a big button that reads "Import Mesh" always needed to keep the intent of the tool obvious? Not Really. And yes, I can provide more functions if needed, perhaps the ability to specify the meshes and materials in engine, would be useful add-on to this. You may find yourself giving more or less flexibility when it comes to designing user interfaces, but it all comes back to who your "user" is. For the purpose of demonstrating the tool in an academic project, I found it easier to keep it simple and easy to be noticed, since the tool performed singular function. This was also my first introduction to Unreal Engine's Editor Utility Widgets, which I found very intuitive to work with.
Takeaway: Keeping your tools, including functionality and interface user-friendly is necessary. Making users jump through hoops to perform simple tasks is never worth it.
3. Different APIs can be confusing
Python has numerous applications - one of the reasons why its so popular. However, this also results in having to deal with various APIs with regards to the application in question. While Blender has various resources and even 3rd party tutorials for the Python applications, I found Unreal Engine's Python API to be particularly challenging to navigate. It's understandable given Python's usage inside Unreal Engine is not a popular option, especially when C++ naturally takes precedence as the primary programming language for the game engine. However, python's ease of usage and familiarity is what convinced me to me try it out, and perhaps that could be the case for other developers who are not familiar with C++.
Here is a small snippet of a function that lets Unreal Engine identify and import a file (in this case, a mesh):
def importAssetsInUnreal(): ### Simplest way of referring a file directory and using the value fileDir = [ " " ] assetTools = unreal.AssetToolsHelpers.get_asset_tools() ### Create asset import data object ### assetImportData = unreal.AutomatedAssetImportData() ### Create data attributes for importing ### assetImportData.destination_path = '/Game/Meshes/' assetImportData.filenames = fileDir ### Importing asset using provided data ### assetTools.import_assets_automated(assetImportData)
In contrast, Blender's Python API works very differently when used to import or export any file:
def importAssetsInBlender(): ### Using API's import_scene operator and passing information ### bpy.ops.import_scene.fbx( filepath='', directory='', filter_glob='*.fbx', ui_tab='MAIN', axis_forward='-Z', axis_up='Y' )
They both have Python at their core of functioning, but they perform differently for the same task. Certainly, its a simplification of the idea, but what it illustrates is that different applications employ and require the understanding of their respective APIs.
Takeaway: The documentation and resources available to you for an application can result in a big difference. It streamlines the processes and opens up gateway to the abundance of resources at your disposal. Taking some time to familiarize yourself with available resources can save hours later. Additionally, I've realized that if the application deserves some learning material, it is wise to contribute to it if you can.
As a result, I am sharing some resources that helped me understand Blender and Unreal Engine Python APIs. In the future, I can make blog posts with specific tutorials for working with both the applications.
Resources:
1. Blender Export Scene Operators - Blender API's export options can seem overwhelming at first, but the sheer number of options at user's disposal is very helpful.
2. Chris Evans Unreal Python Tutorials - Although a little dated, Chris Evans' Python tutorials are immensely useful in understanding the fundamentals.
3. Isaac Oster's Unreal Python Tutorials - Isaac Oster has done helpful work with his trove of Python Unreal resources. One of the few ones on YouTube. He posts them on the Unreal Engine's community page as well.
4. Blender and Unreal Engine Documentation - Elementary yet valuable resources that I keep coming back to. They are your best friends when dealing with both the applications.