Mixer Creation

Like all other types of states, Mixers can be created using Transitions configured in the Inspector or Manually Created in code. Both approaches also allow for Mixers to be nested inside each other.

Transitions

Mixers are usually set up in the Inspector using Mixer Transitions:

using Animancer;
using UnityEngine;

public class PlayMixerOnEnable : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private LinearMixerTransition _Mixer;

    [SerializeField, Range(0, 1)]
    private float _MovementSpeed;

    private void OnEnable()
    {
        _Animancer.Play(_Mixer);
    }

    private void Update()
    {
        // Transitions don't have a parameter to control directly.
        // But once it has been played to create the state, you can access the state's parameter.
        _Mixer.State.Parameter = _MovementSpeed;
    }
}

This is most often the preferred approach since it keeps the code simple and allows the animation details to be configured by non-programmers.

The Mixer Synchronization page explains why the Sync toggle is disabled for the Idle animation.

Manual Creation

If you don't want to use a Mixer Transition, you can create the Mixer yourself using code:

  1. Get references to the child animations you want (they can be AnimationClips or Transitions):
[SerializeField] private AnimationClip _Idle;
[SerializeField] private AnimationClip _Walk;
[SerializeField] private AnimationClip _Run;
  1. Select a Mixer from the Mixer Types table and make a new one. For example, new LinearMixerState().
  2. Add states to it using a collection initializer or by calling Add:
Collection Initializer Manual Add
private LinearMixerState _Mixer;

private void Awake()
{
    _Mixer = new LinearMixerState
    {
        { _Idle, 0 },
        { _Walk, 0.5f },
        { _Run, 1 },
    };
}
private LinearMixerState _Mixer;

private void Awake()
{
    _Mixer = new LinearMixerState();
    _Mixer.Add(_Idle, 0);
    _Mixer.Add(_Walk, 0.5f);
    _Mixer.Add(_Run, 1);
}
  1. Optionally call SetDebugName on the mixer to give it a more descriptive display name to show in the Inspector.
  2. Store a reference to the mixer so you can set its Parameter later on to control its blending.

The following example script uses a LinearMixerState to blend between Idle and Walk, and Run animations based on a Movement Speed slider in the Inspector:

using Animancer;
using UnityEngine;

public sealed class LinearMixerExample : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private AnimationClip _Idle;
    [SerializeField] private AnimationClip _Walk;
    [SerializeField] private AnimationClip _Run;

    [SerializeField, Range(0, 1)]
    private float _MovementSpeed;

    // Keep the mixer state after it's created so we can change the Parameter later.
    private LinearMixerState _MovementMixer;

    private void Awake()
    {
        // Make a new mixer and add children to it using a Collection Initializer.
        _MovementMixer = new LinearMixerState
        {
            { _Idle, 0 },
            { _Walk, 0.5f },
            { _Run, 1 },
        };

        // Or add children one by one.
        // _MovementMixer = new LinearMixerState();
        // _MovementMixer.Add(_Idle, 0);
        // _MovementMixer.Add(_Walk, 0.5f);
        // _MovementMixer.Add(_Run, 1);

        // Don't synchronize the Idle animation (Index 0) with the Walk and Run cycles.
        _MovementMixer.DontSynchronize(_MovementMixer.GetChild(0));

        // Then you can Play the mixer just like a regular clip.
        _Animancer.Play(_MovementMixer);
    }

    private void Update()
    {
        // Set the mixer's parameter to control its current blending.
        _MovementMixer.Parameter = _MovementSpeed;
    }
}

Thresholds

You can either specify the thresholds manually or provide a custom calculation Delegate to MixerState<T>.CalculateThresholds. For Vector2 based Mixers (Cartesian and Directional) you can also use the AnimancerUtilities.CalculateThresholdsFromAverageVelocityXZ extension method.

Nesting

Mixers can have any type of State as their children, including other Mixers.

For example, if you have Mixers for movement in any direction for both regular movement and for moving while injured, you could put both of those in another mixer to allow you to blend the injury level as well. Both of the following approaches have an example of how to do this.

Transition Nesting

If the parent mixer is defined using a Transition then you can assign Transition Assets as its child animations.

To set the parameters of the child mixers you will need to call parentMixer.GetChild(x) and Type Cast the returned state to the appropriate mixer type.

Here's an example of mixer transition nesting:

using Animancer;
using UnityEngine;

public sealed class TransitionNestedMixerExample : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private LinearMixerTransition _MovementMixer;

    [SerializeField, Range(0, 1)]
    private float _InjuryLevel;

    [SerializeField, Range(-1, 1)]
    private float _MovementX;

    [SerializeField, Range(-1, 1)]
    private float _MovementY;

    private MixerState<Vector2> _RegularMovement;
    private MixerState<Vector2> _InjuredMovement;

    private void Awake()
    {
        _Animancer.Play(_MovementMixer);

        // Or just create the state if you don't want to Play it yet.
        // _Animancer.States.GetOrCreate(_MovementMixer);

        _RegularMovement = (MixerState<Vector2>)_MovementMixer.State.GetChild(0);
        _InjuredMovement = (MixerState<Vector2>)_MovementMixer.State.GetChild(1);
    }

    private void Update()
    {
        // The _MovementMixer.Parameter corresponds to the Thresholds assigned above:
        // 0   = Regular.
        // 0.5 = Halfway between Regular and Injured.
        // 1   = Injured.
        _MovementMixer.State.Parameter = _InjuryLevel;

        // And the child mixer parameters correspond to the current movement direction.
        var movement = new Vector2(_MovementX, _MovementY);
        _RegularMovement.Parameter = movement;
        _InjuredMovement.Parameter = movement;
    }
}

Manual Nesting

If you want to set everything up Manually you can simply use a collection initializer or Add the child mixers or transitions the same way you would add AnimationClips.

Since you're creating each of the child states, you can simply keep references to them instead of needing to retrieve them like with Transition Nesting.

Here's an example of manually created nesting:

using Animancer;
using UnityEngine;

public sealed class ManualNestedMixerExample : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private MixerTransition2D _RegularMovement;
    [SerializeField] private MixerTransition2D _InjuredMovement;

    [SerializeField, Range(0, 1)]
    private float _InjuryLevel;

    [SerializeField, Range(-1, 1)]
    private float _MovementX;

    [SerializeField, Range(-1, 1)]
    private float _MovementY;

    private LinearMixerState _MovementMixer;

    private void Awake()
    {
        // Add a Child using the Regular Movement transition with a Threshold of 0.
        // Add a Child using the Injured Movement transition with a Threshold of 1.
        _MovementMixer = new LinearMixerState
        {
            { _RegularMovement, 0 },
            { _InjuredMovement, 1 }
        };

        // Optionally give the mixers names to show in the Inspector:
        _MovementMixer.SetDebugName("Movement");
        _RegularMovement.BaseState.SetDebugName("Regular Movement");
        _InjuredMovement.BaseState.SetDebugName("Injured Movement");

        _Animancer.Play(_MovementMixer);
    }

    private void Update()
    {
        // The _MovementMixer.Parameter corresponds to the Thresholds assigned above:
        // 0   = Regular.
        // 0.5 = Halfway between Regular and Injured.
        // 1   = Injured.
        _MovementMixer.Parameter = _InjuryLevel;

        // And the child mixer parameters correspond to the current movement direction.
        var movement = new Vector2(_MovementX, _MovementY);
        _RegularMovement.State.Parameter = movement;
        _InjuredMovement.State.Parameter = movement;
    }
}