Blender to Unreal FBX Batch Export Static Mesh

I have created a script in blender that batch exports FBX static mesh, textures, collision and LOD (LOD in separate FBX Files) for unreal engine. This script is very useful for indie game developers who want to keep a library of assets in a scene ready for export to Unreal. Advantage is if you have 100 models in your scene and you need to make changes or modifications to models this script will quickly batch export based on selected models.

Paste script in blender> save scene> select all desired mesh> click batch export.

The script takes each mesh resets the transformation to the center of grid and exports each mesh out as an fbx in the saved scene directory. No need to select collision mesh and LOD, they will get exported automatically based on the base model selection. Accidentally selected a collision mesh or LOD, export still works. No Collision mesh or no LOD, export still works!

Exporting base model+collision mesh in blender for unreal compatibility in one fbx file requires the collision mesh to have the same name with a prefix, [UBX_…(Box Collision),USP…(Sphere Collision), UCX_… (Convex Collision)].
eg. UBX_Cube (collision mesh) and Cube (Base Mesh)>Select both meshes> Export FBX.

Exporting LOD and base model in one FBX file in blender is not supported. LOD is exported separately.
LOD must be saved with a suffix …_1, up to …_6 LOD is supported.
eg. Cube (Base Model), Cube_1 (First LOD), Cube_2 (Second LOD)…

Textures are mostly created in Unreal. You can add different materials to different objects, join the objects and export it out to Unreal. In unreal you can assign different textures to the different materials.

*** IF SOMEONE AT BLENDER OR EPIC COULD PLEASE CREATE BLENDER-UNREAL LOD AND BASE MODEL SUPPORT IN ONE FBX FILE THIS SCRIPT WOULD BE PERFECT ***
or if anyone could help me figure this out that would be great.

I will continue adding more to this script. If anybody has any questions, errors or ideas, please post I would be happy to hear your feedback.

Unreal Developers Group:eyebrowlift:
http://blenderartists.org/forum/group.php?groupid=261

https://wiki.unrealengine.com/Static_Mesh_from_Blender
Epic Games has become a main sponsor of the Blender Development Fund, donating €10,000 to improve Blender’s FBX export capabilities: :eek:



[FOR UNREAL TOOLS FULL SCRIPT PLEASE VISIT LINK BELOW]

Here is my script:



#UNREAL TOOLS v1.01       
#NIKHIL JEEWA 
#2014               

import bpy 
import os
         
#################### BATCH EXPORT ###################

class UnrealTools(bpy.types.Panel): 
    bl_space_type="VIEW_3D"
    bl_region_type="TOOLS"
    bl_category = "Unreal"
    bl_label = "Unreal Tools"


    def draw(self, context): 
        layout = self.layout          
        col = layout.column(align=True) 
        col.label(text="Blender>Unreal FBX Batch Export:")
        
        row = col.row(align=True)  
        row.operator("wm.batch_export", text="Batch Export", icon='EXPORT')


class wm_batch_export(bpy.types.Operator):
    bl_idname="wm.batch_export"
    bl_label="Minimal Operator"
    
    def execute(self,context):
        basedir = os.path.dirname(bpy.data.filepath)
        if not basedir:
            raise Exception("Blend file is not saved")
                    
        collision=[]    
        mesh=[]
        lod=[]
        print ("")
        selection = bpy.context.selected_objects
        bpy.ops.object.select_all(action='DESELECT')


        for obj in selection:
            if not obj.name.startswith("UBX_") and not obj.name.startswith("USP_") and not obj.name.startswith("UCX_"):
                if not obj.name.endswith("_1") and not obj.name.endswith( "_2") and not obj.name.endswith( "_3") and not obj.name.endswith( "_4") and not obj.name.endswith( "_5") and not obj.name.endswith( "_6"):
                    mesh.append(obj)
                    print (mesh)


        bpy.ops.object.select_by_type(type='MESH')
        col = bpy.context.selected_objects
        for obj in col:
            if obj.name.startswith("UBX_") or obj.name.startswith("USP_") or obj.name.startswith("UCX_"):
                collision.append(obj)
            if obj.name.endswith("_1") or obj.name.endswith( "_2") or obj.name.endswith( "_3") or obj.name.endswith( "_4") and not obj.name.endswith( "_5") or obj.name.endswith( "_6"):
                lod.append(obj)    
        
        bpy.ops.object.select_all(action='DESELECT')
        for obj in mesh:    
            meshX=obj.name
            meshXo=obj
            obj.select=True
            hasCollision=0
            for obj in collision:
                colX = (obj.name[4:])
                if colX==meshX:
                    hasCollision=1
                    obj.select=True
                    locc = obj.location.xyz
                    rotXc = obj.rotation_euler[0]
                    rotYc = obj.rotation_euler[1]
                    rotZc = obj.rotation_euler[2]    
                    scac = obj.scale.xyz
                    obj.location.xyz = [0,0,0]
                    obj.rotation_euler = [0,0,0]
                    obj.scale.xyz = [1,1,1]
                    locm = meshXo.location.xyz
                    rotXm = meshXo.rotation_euler[0]
                    rotYm = meshXo.rotation_euler[1]
                    rotZm = meshXo.rotation_euler[2]    
                    scam = meshXo.scale.xyz
                    meshXo.location.xyz = [0,0,0]
                    meshXo.rotation_euler = [0,0,0]
                    meshXo.scale.xyz = [1,1,1]
                    name = bpy.path.clean_name(meshX)
                    fn = os.path.join(basedir, name)
                    bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True,axis_forward='-Z', axis_up='Y')
                    obj.location.xyz = (locc)        
                    obj.rotation_euler = [rotXc,rotYc,rotZc]
                    obj.scale.xyz =(scac) 
                    meshXo.location.xyz = (locm)        
                    meshXo.rotation_euler = [rotXm,rotYm,rotZm]
                    meshXo.scale.xyz =(scam) 
                    obj.select=False
                    for obj in lod:
                        lodX=(obj.name[:-2])
                        if lodX==meshX:
                            meshXo.select=False
                            obj.select=True
                            loc = obj.location.xyz
                            rotX = obj.rotation_euler[0]
                            rotY = obj.rotation_euler[1]
                            rotZ = obj.rotation_euler[2]    
                            sca = obj.scale.xyz
                            bpy.ops.object.location_clear()
                            bpy.ops.object.rotation_clear()
                            bpy.ops.object.scale_clear()
                            name =bpy.path.clean_name(obj.name)
                            fn = os.path.join(basedir,name)
                            bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True,axis_forward='-Z', axis_up='Y')
                            obj.location.xyz = (loc)        
                            obj.rotation_euler = [rotX,rotY,rotZ]
                            obj.scale.xyz =(sca) 
                            meshXo.select=True
                            obj.select=False
                    bpy.ops.object.select_all(action='DESELECT')
            if hasCollision==0:
                locm = meshXo.location.xyz
                rotXm = meshXo.rotation_euler[0]
                rotYm = meshXo.rotation_euler[1]
                rotZm = meshXo.rotation_euler[2]    
                scam = meshXo.scale.xyz
                meshXo.location.xyz = [0,0,0]
                meshXo.rotation_euler = [0,0,0]
                meshXo.scale.xyz = [1,1,1]
                name = bpy.path.clean_name(meshX)
                fn = os.path.join(basedir, name)
                bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True,axis_forward='-Z', axis_up='Y')
                meshXo.location.xyz = (locm)        
                meshXo.rotation_euler = [rotXm,rotYm,rotZm]
                meshXo.scale.xyz =(scam) 
                obj.select=False
                for obj in lod:
                    lodX=(obj.name[:-2])
                    if lodX==meshX:
                        meshXo.select=False
                        obj.select=True
                        loc = obj.location.xyz
                        rotX = obj.rotation_euler[0]
                        rotY = obj.rotation_euler[1]
                        rotZ = obj.rotation_euler[2]    
                        sca = obj.scale.xyz
                        bpy.ops.object.location_clear()
                        bpy.ops.object.rotation_clear()
                        bpy.ops.object.scale_clear()
                        name =bpy.path.clean_name(obj.name)
                        fn = os.path.join(basedir,name)
                        bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True,axis_forward='-Z', axis_up='Y')
                        obj.location.xyz = (loc)        
                        obj.rotation_euler = [rotX,rotY,rotZ]
                        obj.scale.xyz =(sca) 
                        meshXo.select=True
                        obj.select=False
                    bpy.ops.object.select_all(action='DESELECT')
                                         
        for obj in selection:
            obj.select = True
                        
        return {'FINISHED'}
###########################################  
     
if __name__== "__main__": 
    bpy.utils.register_module(__name__) 

Hi @nikhil922 , you’re nice but all the tabs are gone and it is difficult to guess your work in python, please?
make a link to the .py file (in zip), please!

Or use the [ code][/ code] tags

Sorry, this is my first time writing python code. I have added the code tags, thanks for the nice gesture.

hi doublebishop, thanks for the tip!

Thks nikhil922! I try to use it…

hi doublebishop, thanks for the tip!

Nice! Thank you so much for sharing!

thanks, I have already solved my issue. you can see my full script here…

Thanks everyone for your posts, Iv solved my issue with collision export and added more. Script is ready for indie production! :slight_smile:

Hi all, Thanks a lot for the blender script, it is indeed very useful and speeds up the blender-to-unreal process. One quick question though: did anyone finally managed to import several LODs automatically into Unreal? (either using the FBX importer, or using another option)? I’d like to import a large number of meshes, each with 4 Levels of Details, and could not find a solution during the past week.
Thanks for the help!