Is it possible to set animation mask default values with an editor script?

This picture is taken from the mask section of animation import settings, for a specific animation. As can be seen, one box is unchecked. I need his box checked for things to work properly.

Right now i’m in a phase of repeatedly reimporting animations, setting this value manually every time will get tiresome very quickly.

Is there any way i can just make all of these boxes checked by default?

Presumably it’s got something to do with this
http://docs.unity3d.com/ScriptReference/Animations.AvatarMask.html
But i’m on Unity 4.6.2, and can’t figure out how to get at this data, so it might’ve been a Unity5 feature, i can only get this far

using UnityEngine;
using UnityEditor;
using System.Collections;

public class importModel : AssetPostprocessor {

    void OnPostprocessModel ( GameObject g ) {
        ModelImporter m = (ModelImporter) assetImporter;
        if ( m.clipAnimations[0].maskType == ClipAnimationMaskType.CreateFromThisModel ) {
            //??
        }
    }

}

Certainly, the mode more useful sounding OnPreprocessAnimation is definitely Unity 5, and the AvatarkMask class was moved to the animtions namespace (still internal for me)

However, here I made a solution that uses SerailizedProperty to find and modify the mask

using UnityEngine;
using UnityEditor;
using System.Collections;

public class importModel : AssetPostprocessor {
    void OnPostprocessModel ( GameObject g ) {
        ModelImporter m = (ModelImporter) assetImporter;
        if ( m.clipAnimations[0].maskType == ClipAnimationMaskType.CreateFromThisModel ) {
            SerializedObject so = new SerializedObject( m );
            SerializedProperty transformMask = so.FindProperty( "m_ClipAnimations.Array.data[0].transformMask" );

            SerializedProperty array = transformMask.FindPropertyRelative( "Array" );
            int size = array.arraySize;

            for ( int i = 0; i < size; i++ ) {
                SerializedProperty element = array.GetArrayElementAtIndex( i );
                SerializedProperty path = element.FindPropertyRelative( "m_Path" );
                SerializedProperty weight = element.FindPropertyRelative( "m_Weight" );
                if ( path.stringValue == "Root/Left_Foot_Handle/Left_Toe_End" ) {
                    weight.floatValue = 1;
                }
            }

            so.ApplyModifiedProperties();
        }
    }
}

Just change line 19 path.stringValue== to whatever you need (eg “hips/spine/chest/neck/shoulder/weapon” etc)
Weight 1 = ticked, 0 = unticked

1 Like

Thank you, this looks good. I don’t quie understand the string value though, do i have to enter the full path of the bone?

For example, my weapon bone is a child of the right hand. Does his mean i’d have to enter:

Hips/Spine/Chest/Shoulder_R/upper_arm.R/forearm.R/hand.R/Weapon

or something to that nature?

Yeah. If you need to check, just put a debug.log(path) inside the loop to see what they all are
Or if there’s only one weapon, maybe just if(path.Contains(“weapon”))

Thanks, here is a cleaned up version that applies the mask to all of the model’s animation clips:

            var bonesToEnable = new List<string>
            {
                "Root/GenericBone1",
                "Root/GenericBone2",
            };
           
            // Enable the bones for ALL of the model's animation clips.
            for (var i = 0; i < modelImporter.clipAnimations.Length; i++)
            {
                var clip = modelImporter.clipAnimations[i];

                if (clip.maskType != ClipAnimationMaskType.CreateFromThisModel) continue;
               
                var serializedObject = new SerializedObject(modelImporter);
               
                var transformMask = serializedObject.FindProperty($"m_ClipAnimations.Array.data[{i}].transformMask");

                var arrayProperty = transformMask.FindPropertyRelative("Array");

                for (var j = 0; j < arrayProperty.arraySize; j++)
                {
                    var element = arrayProperty.GetArrayElementAtIndex(j);
                   
                    if (bonesToEnable.Contains(element.FindPropertyRelative("m_Path").stringValue))
                    {
                        element.FindPropertyRelative("m_Weight").floatValue = 1;
                    }
                }

                serializedObject.ApplyModifiedProperties();
            }