Published Tuesday 19th September 2023

Preparing Blender models for import into the Unity game engine

I've been working in the Unity game engine for about a year now. If you're not already aware, I'm building a medieval open-world MMORPG called Argentauria. I'm also publishing a devlog as I go, for anybody who cares to follow my progress.

On September 12th, the Unity maintainers announced a change to their pricing model which unfortunately means that Unity is no longer a suitable game engine for this project, so I'm actually now pivoting to Godot, another game engine with a very similar feature set, but I've been meaning to write a tutorial on importing Blender models into Unity for some time now, and it might still be useful to anybody who Unity is still a viable option for, so here we are.

Creating models in Blender, and using models in Unity, is beyond the scope of this guide. This is intended for anybody who has already created their models and is ready to move them over into the Unity game engine for integration into an existing game development.

LOD meshes

One of the greatest features of Unity is its LOD Group mechanic. In a nutshell, when an object is moved further away from the camera, Unity can swap it out for an alternative, simpler mesh to reduce the number of vertices and and increase rendering performance. By adding a LOD Group to a game object, you can configure which meshes to show and hide at different distances.

A very handy feature when importing models from Blender, is that you can create each of these meshes within the model file and as long as they're named appropriately, Unity will set up a LOD Group for you.

To do this, within Blender, navigate to the Outliner panel, (located in the top right by default), and make sure the Display Mode is set to View Layer. In this view, you should see a Collection hierarchy and all of the meshes that your model comprises. If any of these meshes contain a level of detail that could be simplified when the model is at a distance, double-click that mesh in this hierarchy to rename, and suffix _LOD0 to it. Then, duplicate and simplify this mesh, make sure it's positioned with the same origin location as the original, and give it the same name but with the suffix _LOD1. So, for example, if your original mesh piece was LargeWoodenPole and comprised 1,000 triangles, you should now have LargeWoodenPole_LOD0 comprising 1,000 triangles, and LargeWoodenPole_LOD1 comprising maybe 500 triangles. Do this as many times as is feasible, incrementing the suffix with each variant and decreasing the triangles as far as you can.

Each variant should be at the same hierarchical position within your collection, and should comprise the same child meshes in equally simplified levels of detail. So if Hand_LOD0 should contain LittleFinger_LOD0, and Hand_LOD1 should contain LittleFinger_LOD1, for example. If your model uses an armature, the hierarchy should be that each variant is attached to the same armature parts.

To avoid confusion while working in Blender, you can tap the eye icons within the Outliner panel to hide these duplicate meshes so that you're only ever looking at the _LOD0 variants. Just remember to mirror any changes that you make to the other versions, and make sure when exporting the model to Unity, you include invisible objects in the export file. Unity should pick these meshes up and automatically create an appropriate LOD Group configuration for you.

Merging meshes

Unity renders the scene by making numerous draw cycles per frame, and for performance you want to reduce the number of cycles that need making as much as possible, given the game engine is aiming to produce at least 30 frames per second, sometimes 60 or even 120 on certain devices. The difference between even just 1 and 2 draw cycles can be notable when this translates to 120 per second vs 240 per second.

Specifically, Unity makes 1 draw cycle per mesh and material combination. So, if 1 mesh comprises 2 materials, this will incur 2 draw cycles. If 2 meshes comprise either the same material or 1 material each, this too will incur 2 draw cycles. Or if 1 mesh comprises 1 material and 1 other mesh comprises 2 materials, this would incur 3 draw cycles.

Thus, where possible, if you have separate meshes sharing the same materials and they don't need to be handled separately, i.e. they're not part of separate armatures and you won't be toggling their visibility independently, you should try to merge these into a single mesh before exporting. This should be as simple as selecting the relevant meshes and hitting Ctrl+J / Cmd+J to join them, then entering Edit mode to fix any intersections:

  1. Select one of the faces and press Ctrl+L / Cmd+L to select all of the faces it's linked to.

  2. Then hit Ctrl+F / Cmd+F and Intersect (Knife) to cut any intersecting faces up neatly. Do this from a few different starting faces, until all of the faces of the mesh have been selected for at least one knife.

  3. Hit A to select all faces and then Mesh -> Merge -> By Distance to remove duplicate vertices.

  4. If selecting a random face and hitting Ctrl+L now selects the entire mesh, you're done.

Origins

When you've imported into Unity, your object will be positioned in the game world based on its origin. That is, the vertices of your mesh are locally positioned within the object, relative to its origin, and the objects global position within the game world is where this origin location is placed. So it's a good idea to make sure the origin is somewhere sensible before exporting, to make subsequent manipulation easier.

If, for example, your model is of a character, you'll most likely want to position that character somewhere on the ground, so it makes sense for its origin to be at the base of the feet. Where if your object is a ball that needs to spin around in all directions, you'll likely want the origin to be in the very middle so that rotations don't cause it to move around weirdly.

The easiest way to accurately select an appropriate origin is to switch to Edit mode, and with Vertex Selection Mode highlighted, select the vertices that make up the corners of where you want your origin to be. With a cube for example, if you want the origin to be at the base of your cube, you'd want to select the 4 corners that make up this facec, or at least the 2 opposite corners. Then Mesh -> Snap -> Cursor to Selected and Blender will move the 3D cursor to the exact center of this selection. Switch back to Object mode and hit Object -> Set Origin -> Origin to 3D Cursor.

It's also just good practice to then reposition your model at 0,0,0 within Blender, so that its origin is located in the middle of the editor grid.

Armatures

If your model has an armature for animation, make sure the mesh parts that need to move with this armature are hierarchical children of it. Within the Outliner panel, (located in the top right by default), with the Display Mode set to View Layer, the collection should show your armature as the top level object with all of the meshes and poses etc as child objects.

Applying transforms

While you're working within Blender, you're sort of creating a series of transform operations that are applied to the base model to create the version you see. For example, if your model is a 2m x 2m x 2m cube and you enlarge it to be twice as long on the Y access, then you do have a 2m x 4m x 2m object but only because you've added a 1,2,1 scale to what is actually still a 2m x 2m x 2m cube. Such transforms are saved in to the file so that Blender, and other editors, know what to apply when they open it, but the root meshes aren't modified yet.

Before exporting into a game engine like Unity, it's important to apply all of the location, rotation, and scale transforms so that the root mesh is updated accordingly and the game engine has a proper, final mesh to work with. Imagine, for example, that your model is of a character facing along the X axis and you want to be able to rotate this character in the game world when walking around. If you haven't yet applied the rotation transforms, the mesh might actually be facing along the Y axis with a 90 degree rotation transform, and in the game world if you have the character dance around and then return to a rotation of 0, it's going to end up facing the wrong way.

To correct this and prepare your model for Unity, in Object mode, make sure all meshes are visible and all cameras and lights etc are hidden, by tapping on the eye icons in the Outliner panel with the Display Mode set to View Layer, and press A to select all objects. Then Ctrl+A / Cmd+A and Apply -> All Transforms. You should notice the Location and Rotation properties reset to 0,0,0, and the Scale properties reset to 1,1,1.

Export

Finally, export your model. Unity supports a variety of file formats, but for various reasons exporting as FBX is the best option. Mainly because FBX files support animations while OBJ files for example do not, and FBX files are also self containing, while the OBJ format for example creates separate material files which can end up messy when working with a large number of models. So, select File -> Export -> FBX.

When exporting as FBX, the export dialog offers a number of options. Here, you can limit the exported file to contain only the selected or visible objects, and/or you can filter the object types to export. You'll nearly always want to deselect Camera and Lamp types and set these up separately within Unity. Remember not to limit to only visible objects if your collection includes LOD varients that you've kept hidden, because you want Unity to find these and set up the LOD groups for you.

For best results, I tend to find that setting Apply Scalings to FBX All is a good call, even after manually applying all transforms.

Set the Forward and Up axis accordingly. If for example your model is of a character facing along the X axis, you'll want to set Forward to X Forward, and set Up to Y Up. Unity uses Y as the vertical axis while Blender uses Z for vertical, so setting these correctly in the FBX file tells Unity how to properly re-orientate on import.

Under Geometry, there's the option to Apply Modifiers. If you've created any modifiers on your meshes and not manually applied them, this option lets you apply on export instead, which can be really useful as it means your Blender file can remain low poly with sub-division modifiers giving it more detail, and that detail will be baked in on export without you having to manually apply and then work with the extra vertices when sculpting or animating. It usually makes sense to leave modifiers un-applied in the Blender file, and keep this option selected when exporting for Unity.

It can also be helpful to select Triangular Faces at this point. Blender can work with irregularly shaped faces but game engines and GPUs really prefer triangles, because this keeps faces flat which means less guess-work when computing how to texture them, and thus less chance of rendering glitches.

Finally, if you're exporting animations, it's a good idea to export each animation to a separate file and to keep those files small by only exporting the animation. You can do this by selecting the animation first, within the Outliner panel, and limiting to Selected Objects within the export dialog. Doing this means that you have individual animation files to load in to animator controllers within Unity, for any models that use the same armature structure, instead of having to bake those animations in to all of the individual models.

Importing into Unity

Drop the resulting FBX file into your Unity assets library, and Unity should automatically pick this up for import. Locate the file within the project files panel and select it to open the inspector.

The correct import settings for you are subject to the model you've created and how you intend to use it within the game engine. There are a lot of options here, and going into detail on all of the inspector settings is beyond the scope of this guide, but I'll cover a few of the basics to get you started.

The inspector is split into Model, Rig, Animation, and Materials tabs. First off, from the Model tab you'll likely want to deselect Cameras and Lights, just in case you accidentally exported those to the file. Make sure Preserve Hierarchy is selected, and you'll probably also want to make sure Normals, Blend Shape Normals, and Tangents are set to Import so that Unity uses the normals and tangents calculated by Blender instead of calculating its own, otherwise any changes you made to things like the normal directions would be lost on import.

If your export included an armature rig, and your model is of a character, you'll want to set the Animation Type on the Rig tab to Humanoid. Unity's physics engine behaves differently for armatures that it knows are humanoid, otherwise it would try to make 2 legged characters fall over when standing on one leg, or cause other similarly erroneous effects.

If your export included an animation, make sure Import Animation is selected from the Animation tab.

If you're importing multiple models that share the same material, for example you might have a range of different buildings sharing the same wall materials, or characters sharing the same skin materials, it's a good idea to have a single material instance within Unity and replace the materials your models use with this. To do so, from the Materials tab you should see a list of each of the materials saved into the FBX, with fields to remap them to exisiting Unity materials.

With everything set appropriately, hit Apply and then drag the object into the game world. Once added to the Hierarchy tree, you should be able to unfold the various mesh parts and click into the individual components like any other game object. LOD groups and armatures etc should already be configured here, along with material mappings and such.

Setting up animations, avatars, material shaders, and modifying the LOD groups, etc, is beyond the scope of this guide. At this point you should have a working game object which can be manipulated in all of the usual ways. Refer to the Unity documentation to actually work with the imported data.

Photo of Ric

Ric

Ric is a senior web and game programmer with nearly 30 years industry experience and countless programming languages in his skillset. He's worked for and with a number of design and development agencies, and is the proprietor of QWeb Ltd. Ric is also a Linux server technician and an advocate of free, open-source technologies. He can be found on Mastodon where he often posts about the projects he's working on both for and outside of QWeb Ltd, or you can follow and support his indie game project on Kofi. Ric also maintains our Github page of useful scripts.

Blog posts are written by individuals and do not necessarily depict the opinions or beliefs of QWeb Ltd or its current employees. Any information provided here might be biased or subjective, and might become out of date.

Discuss this post

Nobody has commented yet.

Leave a comment

Your email address is used to notify you of new comments to this thread, and also to pull your Gravatar image. Your name, email address, and message are stored as encrypted text. You won't be added to any mailing list, and your details won't be shared with any third party.

This site is protected by reCAPTCHA and the Google Privacy Policy & Terms of Service apply.