Simulate [check "Loop Time" + "Apply"] in FBX inspector by script

Hello,

I would like to reproduce in C# the same output than enabling the “Loop Time” checkbox and clicking on “Apply” in the ModelImporter inspector, on an FBX mesh asset. The following doesn’t work:

GameObject fbx = Resources.LoadAssetAtPath<GameObject>("Assets/SomePath/mesh.fbx");
ModelImporter modelImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(fbx)) as ModelImporter;
modelImporter.defaultClipAnimations[0].loop = true;
modelImporter.SaveAndReimport();

I tried a lot of things among using modelImporter.clipAnimations, modifying AnimationClips located in the asset (loaded with AssetDatabase.LoadAllAssetsAtPath), AnimationUtility.SetAnimationClipSettings(), EditorUtility.SetDirty(), modelImporter.SaveAndReimport(), AssetDatabase.SaveAssets(), AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate), AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(fbx))…
Nothing leaves the asset with the checkbox of any animation enabled, and Revert/Apply buttons are disabled (so the editor doesn’t detect any change I guess?).

Does anybody have a piece of code to apply changes made to an FBX asset by script? Especially in the animation clips?

Thanks in advance.

EDIT: By the way, it is a script designed to be executed in the Editor, not at runtime.

I finally found a way to do it. Just add the following script in Assets/Editor:

public class ModelMeshMergeProcessor : AssetPostprocessor
{
    void OnPostprocessModel (GameObject g)
    {
        if (assetImporter is ModelImporter)
        {
            ModelImporter modelImporter = (assetImporter as ModelImporter);

            ModelImporterClipAnimation[] clipAnimations = new ModelImporterClipAnimation[modelImporter.defaultClipAnimations.Length];

            for (int i = 0; i < modelImporter.defaultClipAnimations.Length; i++)
            {
                clipAnimations[i] = new ModelImporterClipAnimation();

                clipAnimations[i].cycleOffset = modelImporter.defaultClipAnimations[i].cycleOffset;
                clipAnimations[i].events = modelImporter.defaultClipAnimations[i].events;
                clipAnimations[i].heightFromFeet = modelImporter.defaultClipAnimations[i].heightFromFeet;
                clipAnimations[i].heightOffset = modelImporter.defaultClipAnimations[i].heightOffset;
                clipAnimations[i].keepOriginalOrientation = modelImporter.defaultClipAnimations[i].keepOriginalOrientation;
                clipAnimations[i].keepOriginalPositionXZ = modelImporter.defaultClipAnimations[i].keepOriginalPositionXZ;
                clipAnimations[i].keepOriginalPositionY = modelImporter.defaultClipAnimations[i].keepOriginalPositionY;
                clipAnimations[i].lockRootHeightY = modelImporter.defaultClipAnimations[i].lockRootHeightY;
                clipAnimations[i].lockRootPositionXZ = modelImporter.defaultClipAnimations[i].lockRootPositionXZ;
                clipAnimations[i].lockRootRotation = modelImporter.defaultClipAnimations[i].lockRootRotation;
                clipAnimations[i].loopPose = modelImporter.defaultClipAnimations[i].loopPose;
                clipAnimations[i].maskSource = modelImporter.defaultClipAnimations[i].maskSource;
                clipAnimations[i].maskType = modelImporter.defaultClipAnimations[i].maskType;
                clipAnimations[i].mirror = modelImporter.defaultClipAnimations[i].mirror;
                clipAnimations[i].rotationOffset = modelImporter.defaultClipAnimations[i].rotationOffset;
                clipAnimations[i].takeName = modelImporter.defaultClipAnimations[i].takeName;

                clipAnimations[i].curves = modelImporter.defaultClipAnimations[i].curves;
                clipAnimations[i].name = modelImporter.defaultClipAnimations[i].name;
                clipAnimations[i].firstFrame = modelImporter.defaultClipAnimations[i].firstFrame;
                clipAnimations[i].lastFrame = modelImporter.defaultClipAnimations[i].lastFrame;
                clipAnimations[i].loop = true;
                clipAnimations[i].loopTime = true;
                clipAnimations[i].wrapMode = WrapMode.Loop;
            }

            modelImporter.clipAnimations = clipAnimations;
            Debug.Log("Updated " + modelImporter.defaultClipAnimations.Length + " animations");
        }
    }
}

Copying all members was a needed step for me. Omitting them was throwing the warning “Split Animation Take Not Found” and AnimationClips were missing in the FBX asset.

3 Likes