import bpy import mathutils bpy.ops.wm.read_factory_settings(use_empty=True) fbx_in = r"Tools/output/explorer_3d/mixamo_extracted/model.fbx" fbx_out = r"AIClient/Assets/Bundles/Characters/Human/Explorer/Explorer.fbx" bpy.ops.import_scene.fbx(filepath=fbx_in) # Find armature and mesh armature = None mesh_objs = [] for obj in bpy.context.scene.objects: if obj.type == 'ARMATURE': armature = obj elif obj.type == 'MESH': mesh_objs.append(obj) print("Imported armature:", armature.name if armature else "None") print("Imported meshes:", [m.name for m in mesh_objs]) # Calculate bounds of meshes min_y = float('inf') for obj in mesh_objs: for v in obj.data.vertices: world_co = obj.matrix_world @ v.co if world_co.z < min_y: # In Blender Z is up min_y = world_co.z print("Mesh lowest Z in Blender:", min_y) # Export FBX with Y-up, -Z forward in blender convention (which converts to +Z in Unity) bpy.ops.export_scene.fbx( filepath=fbx_out, use_selection=False, global_scale=1.0, apply_unit_scale=True, apply_scale_options='FBX_SCALE_NONE', bake_space_transform=False, object_types={'ARMATURE', 'MESH'}, use_mesh_modifiers=True, mesh_smooth_type='FACE', add_leaf_bones=False, primary_bone_axis='Y', secondary_bone_axis='X', axis_forward='-Z', axis_up='Y' ) print("Exported normalized Explorer.fbx")