Animator Controller Layer and Default Weight

I’m making a script which automate character animation tree setup. However I have several issues.
First is default weight. I can’t set default weight for layers.
I use code

attackLayer.defaultWeight = 1.0f;

It’s does nothing. I’m still able to get data from the layer like.

AnimatorStateMachine attackStateMachine = attackLayer.stateMachine;

Works just fine.

Also if try add AvatarMask with code.

attackLayer.avatarMask = m;

Where m begin my AvatarMask, nothing happens.

Any ideas?

I know this is a very old question, but I couldn’t find a solution online and I had the same issue today. So I figured I might as well post it:

When adding a layer with AnimatorController.AddLayer("New layer");, a defaultWeight of 0 is already assigned to the layer, so changing after the layer is added won’t have any effect. What you need to do is to create the AnimatorControllerLayer first, assign it the weight you want, and then add it to the AnimatorController.

So:

var layer = new UnityEditor.Animations.AnimatorControllerLayer
{
    name = "New layer",
    defaultWeight = 1f,
    stateMachine = new UnityEditor.Animations.AnimatorStateMachine() // Make sure to create a StateMachine as well, as a default one is not created
};

controller.AddLayer(layer);
4 Likes

When I duplicate the ‘AnimatorController’ after the changes has been made, the AnimatorStateMachine in the duplicated one would disappear visually… do you have any idea?

ok, after I read a few threads, it appears that layersstate machines are assets, therefore should be saved on disk… read (this) for further details => AnimatorController.AddLayer() doesn't create default AnimatorStateMachine

here’s how it was done:

const string controllerPath = "Assets/AnimatorController.controller";

AnimatorController controller = AnimatorController.CreateAnimatorControllerAtPath(controllerPath);

AnimatorStateMachine stateMachine = new AnimatorStateMachine
{
    name = controller.MakeUniqueLayerName("New Layer"),
    hideFlags = HideFlags.HideInHierarchy
};

controller.AddLayer(new AnimatorControllerLayer
{
    stateMachine = stateMachine,
    name = stateMachine.name,
    defaultWeight = 1f
});

AssetDatabase.AddObjectToAsset(stateMachine, controllerPath);

Sorry for the necro, I’ve just been fiddling with this issue myself in unity LTS 2022 and wanted to throw some notes in here to save someone else some time

  • AddLayer(AnimatorControllerLayer) doesn’t call AssetDatabase.AddObjectToAsset(animatorControllerPath) automatically, if you don’t call this yourself, the state machine will be lost when you relaunch
  • calling AddLayer(AnimatorControllerLayer) with a non-empty state machine causes it to not save properly and appear empty. so if you are going to add states to a layer, make sure you add the layer first

with that in mind, here’s the code i wrote that ended up working the best

AnimatorControllerLayer layer = new AnimatorControllerLayer
{
    name = "layerName",
    defaultWeight = 1,
    stateMachine = new AnimatorStateMachine()
    {
        "layerName" // this just makes some text show up nicely in editor
    }
};

AssetDatabase.AddObjectToAsset(layer.stateMachine, AssetDatabase.GetAssetPath(AnimatorController));
AnimatorController.AddLayer(layer);
MyFunctionThatAddsNodesToStateMachine(layer.stateMachine);
  • AddLayer(AnimatorControllerLayer) doesn’t call AssetDatabase.AddObjectToAsset(animatorControllerPath)

that’s to be expected, as the AnimatorControllerLayer type isn’t a Unity object (does not derive from UnityEngine.Object), as such; one can’t apply the AssetDatabase.AddObjectToAsset function on an argument of type AnimatorControllerLayer.

the stateMachine member of the AnimatorControllerLayer class on the other hand, is a Unity object, therefore it’s the concern; whether one adds it directly (as I’ve done in the demonstration I’ve provided), or by retrieving it (stateMachine) from an AnimatorControllerLayer instance (the way you presented it).

  • calling AddLayer(AnimatorControllerLayer) with a non-empty state machine causes it to not save properly and appear empty. so if you are going to add states to a layer, make sure you add the layer first

states and/or (sub) state machines are affixed to state machines (and not layers), layers are containers of top-level state machines.

to conclude; what has to be saved on disk is the state machine (but not limited to, for instance states; transitions, etc… are also supposed go through AssetDatabase.AddObjectToAsset).