
While Monster Couch slowly picks up velocity I’m still finishing up a side-gig for a 3D mobile game port. On my journey I was excited to use the cloud build to automate the process (and so that I could use the mac mini less :p). I happily set everything up but in he first cloud build something strange happened – all of my Blender models were missing.
I went on to search for the cause only to find out in the Support FAQ that:
“Unity Cloud Build supports “Exported 3d files”. We don’t support “Proprietary 3D files” at this time. A list of which types of files are which can be found here: HOWTO-importObject“
That’s a real pain but the rationale is quite clear: on local machine it’s simple: the user is responsible for providing the licensed software to work with the proprietary formats. It gets slightly more complicated with the hosted build service. It’s doable with Blender since it’s open source and free – the script I’ll be showing you in a minute could be integrated into the service. I guess they will work it out sometime in the future but in the meantime…
Ouch, so how do I export over 150 models without destroying my prefabs?
Luckily Unity uses a python script to import .blend files and turns them internally into .fbx files. If you want to check out the script it can be found at *\Unity\Editor\Data\Tools\Unity-BlenderToFBX.py .
We can use that as a base for our batch exporter – we will be sure that nothing weird happens to our models. Here’s the script updated to accept command line arguments for input and output files. Originally it also depended on the Blender file being already opened so I’ve added a line to make sure it loads the contents of the .blender file.
Export .fbx from .blend
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
blender249 = True import sys try: import Blender except: blender249 = False import bpy if blender249: try: import export_fbx except: print('error: export_fbx not found.') Blender.Quit() else: try: import io_scene_fbx.export_fbx except: print('error: io_scene_fbx.export_fbx not found.') # This might need to be bpy.Quit() raise # Accept command line arguments and load the contents of the .blend file infile = sys.argv[5] bpy.ops.wm.open_mainfile(filepath=infile) outfile = sys.argv[6] # Do the conversion print("Starting blender to FBX conversion " + outfile) if blender249: mtx4_x90n = Blender.Mathutils.RotationMatrix(-90, 4, 'x') export_fbx.write(outfile, EXP_OBS_SELECTED=False, EXP_MESH=True, EXP_MESH_APPLY_MOD=True, EXP_MESH_HQ_NORMALS=True, EXP_ARMATURE=True, EXP_LAMP=True, EXP_CAMERA=True, EXP_EMPTY=True, EXP_IMAGE_COPY=False, ANIM_ENABLE=True, ANIM_OPTIMIZE=False, ANIM_ACTION_ALL=True, GLOBAL_MATRIX=mtx4_x90n) else: # blender 2.58 or newer import math from mathutils import Matrix # -90 degrees mtx4_x90n = Matrix.Rotation(-math.pi / 2.0, 4, 'X') print("moo") class FakeOp: def report(self, tp, msg): print("%s: %s" % (tp, msg)) exportObjects = ['ARMATURE', 'EMPTY', 'MESH'] minorVersion = bpy.app.version[1]; if minorVersion <= 58: # 2.58 io_scene_fbx.export_fbx.save(FakeOp(), bpy.context, filepath=outfile, global_matrix=mtx4_x90n, use_selection=False, object_types=exportObjects, mesh_apply_modifiers=True, ANIM_ENABLE=True, ANIM_OPTIMIZE=False, ANIM_OPTIMIZE_PRECISSION=6, ANIM_ACTION_ALL=True, batch_mode='OFF', BATCH_OWN_DIR=False) else: # 2.59 and later kwargs = io_scene_fbx.export_fbx.defaults_unity3d() io_scene_fbx.export_fbx.save(FakeOp(), bpy.context, filepath=outfile, **kwargs) # HQ normals are not supported in the current exporter print("Finished blender to FBX conversion " + outfile) |
Search the project for every .blend model
We will also need a script that traverses our project recursively and runs the above script for every .blend model. We will also need to rename the .blend.meta files so that we don’t loose any references and finally clean up the .blend files since we no longer need them for our prefabs and scenes. Backup them somewhere before you proceed!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# # blendToFbxExporter.py # # Created by Krzysztof Żarczyński (@iamsed) on 16.11.15. # http://blog.kzarczynski.com/ # Copyright (c) 2015 Krzysztof Żarczyński. All rights reserved. # # # The script exports multiple files from Blender into fbx models. # It searches the path recursively and creates .fbx files next to the .blend files, # then it renames corresponding Unity *.blend.meta files to *.fbx.meta to keep editor references, # !!! then it deletes the .blend files !!! # You need Blender to be installed on your machine. # You need to specify the following command line arguments: # Blender's directory, path to args-Unity-BlenderToFBX.py, input directory (with blend files) # import os import os.path import sys import glob import bpy import fnmatch import subprocess if len(sys.argv) != 7: print("\nusage: --background --python -- ") else: pathToBlender = sys.argv[0] pathToBlenderToFBX = sys.argv[5] path = sys.argv[6] alreadyHaveFBX = [] processedFiles = [] configfiles = [os.path.join(dirpath, f) for dirpath, dirnames, files in os.walk(path) for f in fnmatch.filter(files, '*.blend')] for infile in configfiles: outfilename = infile.replace('blend', 'fbx') if os.path.isfile(outfilename): alreadyHaveFBX.append(infile) else: status = subprocess.call(pathToBlender + ' --background --python ' + pathToBlenderToFBX + ' -- "' + infile + '" "' + outfilename + '"'); os.remove(infile) processedFiles.append(infile) configfiles = [os.path.join(dirpath, f) for dirpath, dirnames, files in os.walk(path) for f in fnmatch.filter(files, '*.blend.meta')] for infile in configfiles: outfilename = infile.replace('blend', 'fbx') if not os.path.isfile(outfilename): os.rename(infile, outfilename) print("Processed files:") print(len(processedFiles)) print("Skipped files (.fbx already exists at the locaton):") print(len(alreadyHaveFBX)) for infile in alreadyHaveFBX: print(infile) |
Sample usage
1 |
blender --background --python "E:\blendToFbxExporter.py" -- "E:\args-Unity-BlenderToFBX.py" "E:\NewUnityProject\Assets" |
Summary
The script exports multiple files from Blender into fbx models. It searches the path recursively and creates .fbx files next to the .blend files, then it renames corresponding Unity *.blend.meta files to *.fbx.meta to keep editor references, then it deletes the .blend files (make your own backup somewhere outside of the project path).
This script uses custom version of Unity-BlenderToFBX.py that Unity uses internally for importing .blend files. It has been changed to allow passing arguments to it and to load the necessary .blend file. You can find the original file at [Unity path]\Editor\Data\Tools\Unity-BlenderToFBX.py
You need Blender to be installed on your machine. You need to specify the following command line arguments: Blender’s directory, path to args-Unity-BlenderToFBX.py, input directory (with blend files)
I have compiled it into a small github repo: blendToFbxExporterForUnity
Edit June 2016
Here is how you can use Blender’s command line: https://www.blender.org/manual/render/workflows/command_line.html
Thanks for reading!
If you have found the post useful please visit us at fb.com/MonsterCouchGames and leave us a like :)
Hello,
Excellent script, thanks for this!
I had troubles running the script with OSx El Capitan, python 3.5, blender 2.77.
I fixed this adding “shell=True” on line 43 of file blendToFbxExporter.py:
status = subprocess.call(pathToBlender + ‘ –background –python ‘ + pathToBlenderToFBX + ‘ — “‘ + infile + ‘” “‘ + outfilename + ‘”‘, shell=True);
Hi there,
I’m an illustrator, about programming… I only know a little of AS3, plus I’m new to Unity, so please bear with me.
As far as I can understand, I should open Mac’s Terminal, go to the directory where Blender is installed and then paste this and hit return:
blender –background –python “/Users/robertogomes/Google\ Drive/VR\ Dev/blendToFbxExporterForUnity-master/blendToFbxExporter.py” — “/Users/robertogomes/Google\ Drive/VR\ Dev/blendToFbxExporterForUnity-master/args-Unity-BlenderToFBX.py” “/Users/robertogomes/Google\ Drive/VR\ Dev/Unity/ExportFromBlenderTest/Assets”
Right? Unfortunately this is what I get: “-bash: blender: command not found”
I’m at it for several hours already, trying to understand what am I doing wrong, reading different posts about running blender from command lines but no success. I also need this to work so I can use Cloud Build because my Mac Mini can’t handle these builds anymore. Can you shed some light on this? Thanks. Keep up the good work.
You could also create an alias for the blender executable:
echo "alias blender=/Applications/Blender/blender.app/Contents/MacOS/blender" >> ~/.profile
Make sure you have the correct path. You can do that by typing ‘ls’ in the terminal and checking if this lists “blender” there?
On Mac this is not next to the app but kind of “inside” the app. This is because on mac apps are hierarchies of files and you need to find the right file inside.
Hi Krzysiek,
Thanks for replying.
Yes when I type “ls” it lists “blender” but I still get the same error…
Roberto:MacOS robertogomes$ ls
blender
Roberto:MacOS robertogomes$ blender –background –python “/Users/robertogomes/Google\ Drive/VR\ Dev/blendToFbxExporterForUnity-master/blendToFbxExporter.py” — “/Users/robertogomes/Google\ Drive/VR\ Dev/blendToFbxExporterForUnity-master/args-Unity-BlenderToFBX.py” “/Users/robertogomes/Google\ Drive/VR\ Dev/Unity/ExportFromBlenderTest/Assets”
-bash: blender: command not found
Roberto:MacOS robertogomes$
I must be doing something wrong… I got the correct paths by dragging them into the terminal and then I’ve put everything together on a note pad before pasting them back in the Terminal.
But when I type “open blender” Blender opens…. grrrr driving me mad
Hm, I don’t know Mac that well, but what happens when you do ‘cd blender’ in terminal there?
For example, I’m in MacOS directory (where “blender” is) and I type “cd blender” I get this:
-bash: cd: blender: Not a directory
So now basically I’m typing the complete path to blender plus –background –python “/Users/robertogomes/Desktop/blendToFbxExporter.py” — “/Users/robertogomes/Desktop/args-Unity-BlenderToFBX.py” “/Users/robertogomes/Google\ Drive/VR\ Dev/Unity/BlendToFBX/Assets/”
and now it is trying to do something but ends up not converting the .blend files
OK, I got something now. I still can’t create the Alias for Blender so I’m typping the complete path instead but now I get have this message:
Read new prefs: /Users/robertogomes/Library/Application Support/Blender/2.76/config/userpref.blend
found bundled python: /Applications/Blender 2.76/blender.app/Contents/MacOS/../Resources/2.76/python
Processed files:
0
Skipped files (.fbx already exists at the locaton):
0
Blender quit
Roberto:~ robertogomes$
Blender didn’t process any files it seems… the .blend files are still in the Assets folder and there is no trace of .fbx files.
Is it my blog converting the characters — (double dash) into — (single dash)?
Make sure you have double dash in the command.
Another thing – could possibly spaces in the path mess something up?
Edit. Yeah it is blog converting characters not marked in code tags.
--
Hi!
I make a *bat file:
cd G:\Steam\steamapps\common\Blender
blender
–background
–python
“G:\blendToFbxExporterForUnity-master\blendToFbxExporter.py”
–“G:\blendToFbxExporterForUnity-master\args-Unity-BlenderToFBX.py”
“G:\blendToFbxExporterForUnity-master\Test”
And I got this:
AL lib: (EE) UpdateDeviceParams: Failed to set 44100hz, got 48000hz instead
found bundled python: G:\Steam\steamapps\common\Blender\2.77\python