FBX Exporter: Binary export doesn't work via editor scripting

I use your Unity FBX Exporter 4.0.1 package and I have to export objects via scripting, like:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

class TestCode
{
    [MenuItem("BugReport/Export selected GameObject as FBX")]
    static void DoMenuItem()
    {
        UnityEditor.Formats.Fbx.Exporter.ModelExporter.ExportObject("Assets/MyExport.fbx", Selection.activeGameObject);
        UnityEditor.AssetDatabase.Refresh();
    }
}

However, the exported FBX file is in ASCII format always. The Export Format settings under Project Settings > Fbx Export don’t affect the exported format.

Right-clicking the object in the Hierarchy and choosing Export to FBX... actually does export the file in binary. I looked through the FBX Exporter code and you pass an additional SettingsObject to the ExportObjects method.

All of this functionality is internal only. Please make the API public instead, I need to export objects via editor-scripting. The reason why I need to export binary is that the ASCII format is just too big, the mesh export is 150MB, which isn’t great for import times in the editor and version control.

I also submitted a bug-report for you:
(Case 1338169) 2019.4: FBX Exporter: Export Binary not working

Same here, did you find a fix?

1 Like

Unity QA was able to reproduce the issue and provided the following workaround, here is their reply:

PS: I don’t use the workaround.

Also ran into this problem and cannot use source code edit workaround. Here’s a dumb as hell, reflection workaround!

private static void ExportBinaryFBX (string filePath, UnityEngine.Object singleObject)
    {
        // Find relevant internal types in Unity.Formats.Fbx.Editor assembly
        Type[] types = AppDomain.CurrentDomain.GetAssemblies().First(x => x.FullName == "Unity.Formats.Fbx.Editor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").GetTypes();
        Type optionsInterfaceType = types.First(x => x.Name == "IExportOptions");
        Type optionsType = types.First(x => x.Name == "ExportOptionsSettingsSerializeBase");

        // Instantiate a settings object instance
        MethodInfo optionsProperty = typeof(ModelExporter).GetProperty("DefaultOptions", BindingFlags.Static | BindingFlags.NonPublic).GetGetMethod(true);
        object optionsInstance = optionsProperty.Invoke(null, null);

        // Change the export setting from ASCII to binary
        FieldInfo exportFormatField = optionsType.GetField("exportFormat", BindingFlags.Instance | BindingFlags.NonPublic);
        exportFormatField.SetValue(optionsInstance, 1);

        // Invoke the ExportObject method with the settings param
        MethodInfo exportObjectMethod = typeof(ModelExporter).GetMethod("ExportObject", BindingFlags.Static | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(string), typeof(UnityEngine.Object), optionsInterfaceType }, null);
        exportObjectMethod.Invoke(null, new object[] { filePath, singleObject, optionsInstance });
    }
6 Likes

So - this is a work-around to the work around if you want to avoid reflection.

Download the GitHub - Unity-Technologies/com.unity.formats.fbx: FBX Exporter tools for editing and exchanging assets between the Unity and Digital Content Creation (DCC) tools such as Maya and 3DS Max and set this up in your packages folder and import the tar.
Open Packages\com.unity.formats.fbx folder in IDE of choice
Find and replace all [internal ] with [public ]*do not include [ ] **Include the space at the end so you don’t replace anything prefaced with internal
Now you can use:

var exportOptions = new ExportModelSettingsSerialize();
exportOptions.SetPreserveImportSettings(true);
ModelExporter.ExportObject(filename, cube, exportOptions);
  • var exportOptions = new ExportModelSettingsSerialize();
  • exportOptions.SetPreserveImportSettings(true);
  • ModelExporter.ExportObject(filename, cube, exportOptions);

The export works but the FBX does not keep the position at all and export at (0,0,0) but the rotation is ok. Any idea?

I want to export a GameObject at the root of the scene in World Absolute position but it always export it Local Pivot even if it is “World Absolute” in Project Settings :

        FieldInfo exportFormatField = optionsType.GetField("objectPosition", BindingFlags.Instance | BindingFlags.NonPublic);
        exportFormatField.SetValue(optionsInstance, 1);

I tried added “objectPosition” “objectsPosition” I even tried “include” but only your field “exportFormat” works. How can you the names of the fields? @LemonLube_1

I found this line in the package : https://github.com/Unity-Technologies/com.unity.formats.fbx/blob/6999d103206d069b00edabcade603ccbad07602d/com.unity.formats.fbx/Editor/FbxExporter.cs#L3719

EDIT : I found it !

Type optionsPositionType = types.First(x => x.Name == "ExportModelSettingsSerialize");
FieldInfo exportPositionField = optionsPositionType.GetField("objectPosition", BindingFlags.Instance | BindingFlags.NonPublic);
exportPositionField.SetValue(optionsInstance, 1);

Add these lines to the @LemonLube_1 solution!

I printed all type possible with these lines :

        foreach(Type type in types)
        {
            Debug.Log("type : " + type);
        }
1 Like

FBX Exporter 5.1.0 pre
Developer’s Guide | FBX Exporter | 5.1.0-pre.1 (unity3d.com)

using UnityEngine;
using UnityEditor;
using System.IO;
using UnityEditor.Formats.Fbx.Exporter;

public class MyFBXExport : MonoBehaviour
{
public GameObject[ ] meshCombiners;

public void Export()
{
ExportModelOptions exportSettings = new ExportModelOptions();
exportSettings.ExportFormat = ExportFormat.Binary;
exportSettings.KeepInstances = false;

for (int i = 0; i < meshCombiners.Length; i++)
{
string filePath = Path.Combine(Application.dataPath, “MyExport”, meshCombiners*.gameObject.name + “.fbx”);*
ModelExporter.ExportObject(filePath, meshCombiners*.gameObject, exportSettings);*
}
}
}

This limitation also affect tools developed by Unity. For example Unity recorder package can export as FBX, but only in ASCII.
https://unity3d.atlassian.net/servicedesk/customer/portal/2/IN-20902

Perhaps it is possible to reopen linked bugs if the API is available in FBX Exporter 5.1.0 pre.

resurrecting this post since I came across this recently. Here’s some addition to the reflection code above if you need to export more than a single mesh as an fbx with binary format. Requiring passing a dictionary with a private type took a bit to figure out the right syntax for so I’ll pass this on in case anyone else needs it.

/////// this is some absolute clown shit.....
Type[] types = AppDomain.CurrentDomain.GetAssemblies().First(x => x.FullName == "Unity.Formats.Fbx.Editor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").GetTypes();
Type optionsInterfaceType = types.First(x => x.Name == "IExportOptions");
Type optionsType = types.First(x => x.Name == "ExportOptionsSettingsSerializeBase");

Type exportDataType = types.First(x => x.Name == "IExportData");
Type dictionaryType = typeof(Dictionary<,>).MakeGenericType(typeof(GameObject), exportDataType);

// Instantiate a settings object instance
MethodInfo optionsProperty = typeof(ModelExporter).GetProperty("DefaultOptions", BindingFlags.Static | BindingFlags.NonPublic).GetGetMethod(true);
object optionsInstance = optionsProperty.Invoke(null, null);

// Change the export setting from ASCII to binary
FieldInfo exportFormatField = optionsType.GetField("exportFormat", BindingFlags.Instance | BindingFlags.NonPublic);
exportFormatField.SetValue(optionsInstance, 1);

// Invoke the ExportObjects method
MethodInfo exportObjectMethod = typeof(ModelExporter).GetMethod("ExportObjects", BindingFlags.Static | BindingFlags.NonPublic, Type.DefaultBinder, new Type[] { typeof(string), typeof(UnityEngine.Object[]), optionsInterfaceType, dictionaryType }, null);
exportObjectMethod.Invoke(null, new object[] { fbxPath, objectsToExport, optionsInstance, null });

frankly ridiculous that this hasn’t been fixed in the 3 years since this was posted. It seems like it should be a 5 minute fix to add a new public method that takes the export type as input.

1 Like