I’ve written an importer script for Blender files in Unity 3D that imports the model correctly without forced rotations. Transforms, hierarchies, animations, etc are fully preserved when loading a .blend file into Unity 3D with this importer.
https://github.com/EdyJ/blender-to-unity3d-importer
I consider Blender the “Unity 3D” of the 3D modeling tools. Everything is exquisitely arranged and well-structured. When you’re a bit used to it you can find what you’re looking for intuitively, while everything else can be easily ignored.
The problem
Blender’s coordinate system is right-handed (+Z up) while Unity’s is left-handed (+Y up). The built-in Blender importer in Unity 3D just rotates the model -90º around the X axis effectively turning the original Z into Y. As result, imported GameObjects are given a rotation (-90,0,0). While this is ok for static and inanimated models, it can be a pain for models that need to be rotated in-game, or use orientation-based components such as WheelColliders. Specially cumbersome is rotation with scripting, as one needs to have the X-90 rotation in consideration.
Issues with the default importer are:
- GameObjects are imposed a X-90 rotation.
- Forward orientation might point -Z (backwards), should be +Z.
- As result of the rotation X-90, components added to the GameObjects will use that orientation. In the above picture a WheelCollider added to pivot_l1 points horizontally instead of vertically.
The solution
My script imports the Blender file into Unity 3D as expected:
- Complete hierarchies are preserved with their correct transforms (position, rotation, scale).
- No artificial rotations are imposed in the imported model: if a rotation in Blender was [0,0,0] the rotation in Unity will be [0,0,0].
- Optionally the forward orientation can be reversed for matching the Unity’s convention (+Z).
- Keyframe-based animations in Blender are correctly converted to animation clips in Unity. The animations will look the same in both Blender and Unity.
Bonus
In addition to merely import the file, the importer offers a couple of valuable tools that can be used with any 3D model format, not only Blender.
- Per-object commands: Include specific keywords in the name of any object in the 3D file and some actions will be performed with it. Actual actions include removing the MeshRenderer and adding a MeshCollider.
- Mesh instance optimization: Removes identical meshes and replaces duplicates with references to an unique copy. Works with any 3D file format, not only Blender.
- New menu option in Unity “GameObject > Optimize mesh instances in this scene”: Launches the instance optimization in the loaded scene, replacing the duplicated objects with references to an unique copy. This effectively reduces the size of the builds, as only the referenced meshes are packaged. Non-referenced meshes are excluded from the build even if they come from the same file.
Go to the GigHub page for usage instructions.
Exporting to FBX
Sometimes a .blend file might take a long time to get imported into Unity 3D (several minutes). The solution is to export the model to FBX and import this file into Unity instead of the .blend file. When exporting the file to FBX ensure to leave the default options:
You can disable (shift-click) the Camera and Lamp objects as they are imported as empty objects and have no utility in Unity 3D.
In Unity 3D add [importer.forcefix] to the name of the fbx file for invoking the importer.
Addendum
In my opinion there’s only one annoyance in Blender that should be addressed in order to make Blender 100% perfect for Unity 3D: disabling or bypassing the use of the inverse transform in parenting, so the parenthood is established more like Unity 3D actually does.
By default, when two objects are parented in Blender (Ctrl-P) there are two transforms involved: direct and inverse. Read a good clarification here. Unity 3D imports the direct transform only, so when a child object has both direct and inverse transforms, then the imported GameObject won’t surely look as expected.
Actual workarounds are:
- Parenting without inverse: use Shift-Ctrl-P for parenting instead of Ctrl-P (documentation here). The problem here is that the actual relative position/rotation/scale of the object with regards to the parent is not preserved. The child’s local transform may need to be readjusted. When rigging a model, parenting without inverse should be used prior to actually editing the child’s transform to its final relative position/rotation/scale.
- Clear inverse transform: Alt-P offers this option. The problem is the same as above: actual relative transform is not preserved so the child object may need to be re-arranged.
The solution would be a new parenting option in Blender (maybe Shift-Alt-P?) that works like in Unity 3D: the child should receive a local (direct) transform that matches the actual relative position, rotation and scale with regards to the parent at the time of parenting, without involving an inverse transform. Just as Unity 3D does when parenting in the Hierarchy panel.
Anyone with experience in Blender add-ons out there? 🙂
Just setup your script, really impressed – I’ve been looking for a script or solution all day and this is the first complete solution to this headache. Thank you so much for your work, I really appreciate it.
Hey thanks for the efforts. Only issue I’m having at the moment involves aStar pathfinding which requires the main asset has the same name as the interior assets (ie the mesh) and therefore doesn’t like the [importer] tages at end of file. Wonder whether there’s a way of adapting this with say a preference file that sits in a folder that affects all assets within that folder? ie script searchs for preference file in folder on Asset import and applies those settings? Anyway still very useful, at the moment I’ll just have to rename my meshes as well as the file name. Cheers.
If you look at this screenshot you’ll see the issue. The file name uses square brackets but the internal mesh is translated down to underscores so file name and mesh don’t match.
http://tinypic.com/r/qrf155/8
http://tinypic.com/r/an0t3c/8
Maybe this is just an issue with AStar Pathfinding Project but perhaps might cause issues in future?
Thank you!
You could easily edit the script for triggering the importer based on your conditions.
Also, the project is hosted at GitHub. If you want to implement searching for a preference file, feel free to fork the repository and make a pull request.
Yep just working on an amendment to search for a folder named with the [importer] etc within the same directory. Should solve another issue with AStar which needs the asset also inside Resource folder as well! Will try to do it properly and fork etc but I’m just learning this whole git/fork/C# shenanigans. Thanks again for the headstart!
Hey I seem to have managed to come up with something. Amended lines 42-48 to this which seems to work for the meantime. Note you now need a folder inside the model fodler to be named [importer-opt-zreverse] for example. Note I’ve changed it from dot syntax.
string filePathImporter = Directory.GetDirectories ((Path.GetDirectoryName (filePath)), "[importer*")[0].ToString();
int i1 = filePathImporter.LastIndexOf('[');
int i2 = filePathImporter.LastIndexOf(']');
if (i1 < 0 || i2 = i2) return;
string[] tokens = filePathImporter.Substring(i1+1, i2-i1-1).Split('-');
Hey, have you tried just renaming the folder where the files are actually located? You don’t need to modify all the files. If the containing folder has the [importer] tag then all files inside are loaded through the importer.
“renaming the folder where the files are actually located” Yes but for AStar the models (NavMesh mainly) need to be in the root of a Resources folder so can’t rename the parent folder. But the above solution seems to get round this. Haven’t tried it it earnest yet.
This should prove more robust (lines 31-60). Will search for folder first and then fallback to original behaviour.
string[] directorySearch = Directory.GetDirectories ((Path.GetDirectoryName (filePath)), "[importer*");
string[] tokens;
int i1;
int i2;
if (directorySearch.Length > 0) {
string filePathImporter = directorySearch[0];
i1 = filePathImporter.LastIndexOf ('[');
i2 = filePathImporter.LastIndexOf (']');
if (i1 < 0 || i2 = i2)
return;
tokens = filePathImporter.Substring (i1 + 1, i2 - i1 - 1).Split ('-');
} else {
i1 = filePath.LastIndexOf ('[');
i2 = filePath.LastIndexOf (']');
if (i1 < 0 || i2 = i2)
return;
tokens = filePath.Substring (i1 + 1, i2 - i1 - 1).Split ('.');
}
This looks really great. We have one outstanding problem still that I can’t tell if your solution addresses, or if there is something I am missing in Blender:
When importing an animation from Blender, Unity automatically assigns “zero” keyframe curves to non-animated bones. Have you found any way to stop this?
Hey Scott, thank you very much! I haven’t tested animation with bones yet, but if you could send me a sample Blender file to edytado@gmail.com I can give it a try.
Just found this script and it’s the closest fix to a problem I’m having so far. But it’s not quite there, unless I’m doing something wrong.
Here’s a blender file for reference: cube [importer].blend
Blender 2.70
Unity Pro 4.3.1f1
The model is a cube with a couple vertices moved and a single bone. The bone has no rotations in blender, but when imported into Unity, it gets rotated around Y (90 deg) and Z (-90 deg). I need it to come in with 0 rotations, just like in Blender.
Your script purports to fix this, if I understand your explanation correctly, but doesn’t seem to work? Or am I doing something wrong?
And I also noticed the mesh object gets moved under the armature? That may not actually matter, but it looks odd when comparing it with a default Unity import.
As an aside, I didn’t even know you could write asset post processors in Unity. So I learned that, at least. Thanks for the work so far!
While I still have the problem mentioned above, I took a few minutes and added to your code. I added a custom asset type to embody the importer options and added code to the importer to load a custom asset with the same name as the blender file. So now there’s no need to rename the blender file. And you get the ability to change importer options right in the inspector. Options in the file name can still be used and will override options in the custom asset. These changes required a restructuring of the file/folder containing your script.
I believe this may also resolve Malcolm’s issue.
When I get a chance, I’ll have to fork your git repo (when I figure out how to since I’ve never really used git) and submit a pull request.
OK, figured out github, I think. I’ve submitted a pull request with my changes, hopefully (I’m frdfsnlght on GitHub).
Hi Tom, many thanks for the update! I’ll review and merge it shortly. Sounds like the custom asset type is the correct way to go!
About your problem with rotation, I haven’t done any test with armatures / bones yet as I haven’t had the need of using them in Blender/Unity so far. Looks like they require a specific treatment.
Could you add a simple animation to the bone in your example? Not only the base rotation must be correct, but the animation must also perform properly.
Ah, that would explain it then. I guess I read too much into your description.
I will add an animation to the provided sample tomorrow morning and let you know.
Yes, the custom asset has all sorts of potential uses since it would allow for much more complex options if necessary, as well as a custom inspector editor if you really wanted it.
Thanks for taking a look!
OK, I couldn’t wait. Here’s a link: cube [importer].blend
I’m almost a complete noob at animating in Blender, so I hope I did it right.
My ultimate expectation/hope is that when the model is imported into Unity, the root bone (Root) is oriented such that if I procedurally rotate it around Unity’s Y axis, it would rotate the same way as it rotates in the animation around Blender’s Z axis. I hope that made sense.
Basically, I have a case where the model will eventually have animations controlling some bones, and code controlling other’s. As it is, when Unity imports bones from FBX files, they come in with all sorts of weird rotations and can’t be rotated in any kind of sensible code (the imported animations work fine, however) . My goal is if a bone in Blender doesn’t have any rotations, then it shouldn’t have any rotations in Unity either (after importing). It’s basically the problem of converting a RH/Z Up coordinate system to a LH/Y Up system, but you already know that. You seem part way to a solution.
Here’s some reading for you.
I’ve been playing with the importer and the blender sample I’ve provided and I see some basic problems, unless I’m not understanding what your importer is supposed to do.
The sample imports normally (w/o your post processor) as an empty object with 2 children: Armature (rotated X-90) and Cube (contains the mesh and is NOT rotated). The Armature object contains a single Root bone (rotated X+90, Y-270).
After your importer runs, the Armature is NOT rotated (which is good), but the Cube object IS rotated X+90 (which isn’t good). And, of course, my original problem is still there: the Root bone under Armature is now rotated Y-90, Z-90 (not good).
The RotateMesh method is never actually applied to ANY mesh objects (I added some debugging code to prove this), so isn’t doing any good.
I’ve been able to add a couple lines to fix the bone rotation, but I’ve ignored fixing the mesh for now. It seems some code restructuring would be in order to really fix that.
Any thoughts on any of this? Or am I missing something?
Hey Tom, sorry for the delay. I’ve been busy with other project. Tomorrow I’ll review and merge your updates, and I’ll test the sample files to find a solution.
Hi Edy,
I followed the instructions but Unity is giving me an error : “Assets/Editor/EdysBlenderImporter.cs(5,1): error CS8025: Parsing error”
There must be a braket missing or something like that.
Do you get the same error?
Thank you!
This seems broken in Unity 4.6 – in particular rotations?
At least it is when I open an old 4.5 project.
That’s weird. It’s seemed to of fixed itself with me doing nothing at all. I can’t figure out what happened but at least it works now.
Sometimes Unity loads the imported asset from the Cache Server instead of re-importing it.
Thank you so much!
I noticed it’s still being maintained and updated for Unity 5. This was a life saver (or at least a Blender-Unity one).
I was having a crazy hard time with fbx files I was trying to export-import. Spent hours trying to get my code working right and using weird work-arounds because of the orientation problems.
Hope it continues to be maintained, so far so good!
I just noticed your Addendum, I’ll have to try that shift+ctrl+p way of parenting cause I think that’s where I was running into some of my problems.
Yes, this script is part of my own core tools for Unity 🙂
I’d also wish to have a proper way of parenting objects in Blender. An add-on script for Blender would be perfect.
Hello Edy, thanks for the great script! I have to ask though, have you ever tried exporting a file with linked groups in that file?
For me, when trying to do this with .fbx, my model comes in facing down (works great without the linked group(s) in the file).
Wondering if you have ever seen this before.
Joe, I’m contacting you by email. I haven’t tested such setup, and it would be great to have some files to test.
Thank you so much for providing this. I just spent days trying to get my Blender creation into Unity without having the rotation all screwed up. Great work and I’m happy to donate something if you’ve got PayPal.
I haven’t tested it extensively but first impressions of this – “wow!”
This is exactly what I’ve been looking for.
I tried writing my own custom export script in blender, spent days on it but it kept producing unexpected results.
Great work! 🙂
WOW,you are god!
It save my tons of time!! Thank you!!!!