Dev Blog

Hi, this is the Stranded III development blog (see also Forum Thread, Comment Thread).

Overview (116 Entries)

Entry 27 - Unity + Blender = WAR! - July 13, 2015

Unity + Blender = WAR!
Today I tried to optimize my model import workflow. My aim was to get the following:

√ A simple list of steps to get my Blender models into Unity
√ Rotation of [0, 0, 0] in Unity = rotation in Blender
√ Scale of [1, 1, 1] in Unity = scale in Blender
√ Materials and textures should work too

I have read that FBX is the best choice as a format for my Blender models.

Hint: Unity also uses FBX internally when you use *.blend files directly. This is only possible when Blender is installed. Unity then secretly runs Blender in the background and converts the blend files to FBX. You can't see this and you will never see any FBX in your project but this is what actually happens in the background.

So at this point you might think: Why isn't he using the *.blend files directly then? Sounds pretty convenient! No conversion/exporting in Blender required!

Unfortunately it's not that easy.

Problem 1: Axis of evil
Unity and Blender use different coordinate systems because they really love to torture people!
IMG:https://stuff.unrealsoftware.de/coordinates_unity_vs_blender.jpg

There's no fancy x, y, z labeling on the Blender side but here's a secret: The color coding for axis is ALWAYS like this (unless someone screwed something up):
• red = x
• green = y
• blue = z

Luckily it's easy to remember this because colors are commonly saved as RGB (red, green, blue) values in digital systems and this order maps to the alphabetic order of x, y and z!

Ooops. Getting of the point. Well the problem of the different systems is: Objects won't be rotated in Unity like they are rotated in Blender. This is bad but there are multiple ways to fix it:

× Use an empty game object as parent of your model in Unity and then rotate the model inside it but not the parent. Now whenever you want to move/rotate/scale the model you only touch its parent. This hides the messed up rotation but of course it costs additional performance/memory for the empty parent object. It probably doesn't cost much but it's a pretty dirty "fix" nevertheless.
See: http://docs.unity3d.com/Manual/HOWTO-FixZAxisIsUp.html

× Just rotate the model in Blender! Seems like an easy fix but it's not convenient and doesn't feel right either.

√ Export the model with correct axis conversion. That's what I want to do. It means that I can't use *.blend files directly but it seems to be the best approach.

So from that moment on I knew: My list of steps would at least involve the steps in Blender for exporting FBX files. Good to know that there aren't a lot of settings for that...
But hey, the default FBX export rotation setting is the right one already so the rotation is not a problem anymore... at least for the moment...

Problem 2: Materials
I also faced a problem with materials but this probably just happened because I'm such a Blender noob. In Blender it's sufficient to simply load a texture. You can directly UV map it and also see it on your mesh. You don't need to setup a material to make it work. However Unity needs that material for the import because it will make a Unity material from it and it will especially also use the name of that material. It took me a while to find out how that works. Before that I always got strange materials with "No Name" or "None" as name which aren't very descriptive names. By the way: You can also rename the auto-imported materials yourself but a reimport will then create a new material again unless you disable the material import in Unity.

Problem 3: Scale
I wanted the scale [1, 1, 1] in Unity to show my mesh in the original size from Blender. 1 Blender unit (that's the edge length of a blender grid cell) is supposed to be 1 Unity unit and in my scale 1 unit should be 1 real world meter.

Hint: It's really important to get model scales right for various reasons. Physics are one very important point. Physic systems are designed to work best with a specific scale. You will have to do adjustments to certain values to make it work well with other scales. Otherwise your objects are too small/big to collide/react properly and everything will look either too slow or too fast. Of course there are many other problems with wrong scales. For example the limited floating point number precision...

The bad thing about Unity and FBX is that Unity applies a standard scale factor to all FBX files. This scale factor is 0.01. I searched it and someone wrote that this is a fix from Unity for Maya because Maya uses cm as default unit and not m so everything is 100 times bigger when imported and Unity needs to compensate that (I'm not sure if that's really correct but it seems legit). Of course you could also use Maya's export scale factor to fix this but that would be too easy I guess.

So to fix that I have to change the scale factor for EVERY model I import by setting that value in Unity from 0.01 to 1. I found an automated solution for that: Unity's Asset Postprocessor scripts. Someone posted one somewhere. I just refined it a bit to only affect FBX files:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using UnityEditor;
using UnityEngine;
using System.IO;

public class ModelImportScale : AssetPostprocessor {
    private const float FBXScale = 1f;

    private void OnPreprocessModel() {
        ModelImporter importer = assetImporter as ModelImporter;
        if (importer != null) {
            if (Path.GetExtension(importer.assetPath) == ".fbx") {
                Debug.Log("FBX Import Postprocessor: " + importer.assetPath + ", use globalScale: " + FBXScale);
                importer.globalScale = FBXScale;
            }
        }
    }
}

Additionally I learned (trial & error) that the "Apply Unit" checkbox in Blender's FBX exporter MUST NOT be checked to make the scale thing work properly. At least it seems to be like that.

Problem 4: Scaling and rotation still being weird sometimes
So the stuff above seemed to fix my problems. The models had the right scale and rotation but then after checking the values in Unity I noticed that strange stuff was going on. When I dragged the imported models into my scene I noticed that some had the correct scale of [1, 1, 1] but some others had very strange scale values. The size was correct but the values were unexpected. Same for some rotations.
So I was forced to search for solutions again and I found out that Blender has this "Apply object transformations" stuff. So when you transform the model in object mode in blender it's different to transforming all vertices/faces in edit mode. When you actually want to make something the default rotation/scale you have to apply it first (at least when you rotated/scaled in object mode). This is a very nasty pitfall if you don't know about it.

So I applied the stuff, exported again and the scale was fine! [1, 1, 1] for all models and having the right size at the same time! Awesome. BUT the rotation is now always [-90, 0, 0] in Unity! I want it to be [0, 0, 0] though! This must somehow be related to the different axis I guess but I didn't find the right configuration yet to solve this issue.

Conclusion
Using Unity with Blender is pretty annoying and problematic. I basically wasted a whole day on this and it's still not working correctly.

Next thing I will have a look at is probably this blender Unity import editor script from Edy:
https://github.com/EdyJ/blender-to-unity3d-importer

Edit 13.07.2015:
Today I did some more research. Edy's script is quite complex so I searched for a shorter one and found this:
http://wiki.unity3d.com/index.php/FixBlenderImportRotation
I converted it to C# and added the scale fix. Everything seems to be okay for now! Finally!

Disqus

blog comments powered by Disqus