AssetPostProcessor - Mecanim...

I can’t figure out how to set animation settings for Mecanim animations in AssetPostProcessor.

On either OnPreprocessModel or OnPostProcessModel, the ModelImporter.clipAnimations does not contain any entries.

During OnPostProcessModel, AnimationUtility.GetAnimationClips does not return anything.

Googling around I found some people using ‘Object.FindObjectsOfType()’. But two issues arise.

  1. it often returns more animations than are being processed currently (to be expected really if you think about it)
  2. If I get the ‘AnimationClipSettings’ from it, it doesn’t actually update the settings as I want them… nor do I know what setting to change to make it ‘Bake Into Pose’.

Here’s what I need really. I want it so that all my models that are imported have their animations set to have all three root transforms (rotation, positionY, positionXZ) to be ‘Bake Into Pose’ and ‘Based Upon Original’.

Of course this is NOT the default import setting, which is really annoying, and I have far too many animations to be constantly doing this by hand for every single animation. But of course, post processing mecanim settings has little to no documentation what so ever.

Any help would be much appreciated!

bump

Hi

The only solution I have found is to manually create a ModelImporterClipAnimation[ ], fill it up with data and assign it to clipAnimations. Note that even after model is imported once, you cannot modify clipAnimations elements from an editor script. To get the data you can either use an FBX parser or use the data Unity already parsed in importedTakeInfos variable. importedTakeInfos is a NonPublic Property which can be accessed by Reflection. Credits to AlkisFortuneFish for this nice solution.

More details:

Alternatively there are 2 interesting release notes for Unity 5.0:
http://unity3d.com/unity/beta/5.0/release-notes

  • Added AssetPostProcessor.OnPreProcessAnimation, this new callback is called just before animation clips are created.

  • Added ModelImporter.defaultClipAnimations (list of ModelImportClipAnimation based on TakeInfo) and ModelImporter.importedTakeInfos (list of TakeInfo from the file).

  • Added API for Avatar

BTW you still need to assign avatar rig for every animation manually, I did not found a way around that in Unity 4.x so far.

Here is my Editor script I use with Unity 4.x, customize to your liking…

using UnityEngine;
using UnityEditor;
using System.Reflection;

public class CustomImportSettings : AssetPostprocessor
{
    void OnPreprocessModel()
    {
        ModelImporter importer = assetImporter as ModelImporter;
        importer.importMaterials = false;
    }

    public void OnPostprocessModel(GameObject obj)
    {
        ModelImporter modelImporter = (ModelImporter) assetImporter;

        if(modelImporter.assetPath.Contains("@")) { /*For animations*/
            PropertyInfo prop = typeof(ModelImporter).GetProperty("importedTakeInfos", BindingFlags.NonPublic | BindingFlags.Instance);
            TakeInfo[] ti = (TakeInfo[]) prop.GetValue(modelImporter, null);
            if(modelImporter.clipAnimations.Length == 0) modelImporter.clipAnimations = SetupDefaultClips(ti);
        } else { /*For models*/
            modelImporter.importAnimation = false;
        }
    }

    ModelImporterClipAnimation[] SetupDefaultClips (TakeInfo[] importedTakeInfos)
    {
        ModelImporterClipAnimation[] clips = new ModelImporterClipAnimation[importedTakeInfos.Length];
        for (int i = 0; i < importedTakeInfos.Length; i++) {
            TakeInfo takeInfo = importedTakeInfos [i];
            ModelImporterClipAnimation mica = new ModelImporterClipAnimation ();
            mica.name = takeInfo.defaultClipName;
            mica.takeName = takeInfo.name;
            mica.firstFrame = (float)((int)Mathf.Round (takeInfo.bakeStartTime * takeInfo.sampleRate));
            mica.lastFrame = (float)((int)Mathf.Round (takeInfo.bakeStopTime * takeInfo.sampleRate));
            mica.maskType = ClipAnimationMaskType.CreateFromThisModel;
            mica.keepOriginalPositionY = true;
            mica.keepOriginalPositionXZ = true;
            mica.keepOriginalOrientation = true;
            mica.lockRootHeightY = true;
            mica.lockRootPositionXZ = true;
            mica.lockRootRotation = true;
            clips [i] = mica;
        }

        return clips;
    }
}

Here is my version of this in Unity 5.6. Much easier now:

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

public class BakeXZSetterPostProcessor : AssetPostprocessor
{
    private static readonly string[] keywords = new string[]
    {
        "Attack",
        "Idle",
        "Death1",
        "Revive1",
        "Block",
        "GetHit"
    };

    public void OnPostprocessModel(GameObject root)
    {

        // Modify ModelImporter meta data and reimport the asset
        ModelImporter modelImporter = assetImporter as ModelImporter;

        if(root.name.Contains("RPG-Character@"))
        {
            foreach(string kwd in keywords)
                if(root.name.Contains(kwd))
                {
                    ModelImporterClipAnimation[] clipAnimations = modelImporter.clipAnimations;

                    foreach(ModelImporterClipAnimation clip in clipAnimations)
                        if(!clip.lockRootPositionXZ)
                        {
                            Debug.Log("Locking root motion XZ on RPG animation, clip : " + root.name);

                            clip.lockRootPositionXZ = true;
                        }

                    modelImporter.clipAnimations = clipAnimations;
                }
        }

    }
}

thanks Zyxil, it works well, only a small problem, every time after postprocess, the gameobject in editor become unapplied and popup a dialog, i have to manual click apply, do you have same issue?

I have the same issue, if I use an AssetPostprocessor I cannot change anything and apply manually in the Inspector.

EDIT Solved it by using Unity - Scripting API: AssetImporter.importSettingsMissing to only apply my settings on the first time I Import an asset. This enables us to also use the Inspector to add changes and apply them.