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. This can be inside a Transition Asset as demonstrated in the Mixers Samples or by using an inline transition like this:
using Animancer;
using UnityEngine;
public class PlayMixerOnEnable : MonoBehaviour
{
[SerializeField] private AnimancerComponent _Animancer;
[SerializeField] private LinearMixerTransition _Mixer;
[SerializeField, Range(0, 1)]
private float _MovementSpeed;
protected virtual void OnEnable()
{
_Animancer.Play(_Mixer);
}
protected virtual 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:
- Get references to the child animations you want (they can be
AnimationClip
s or Transitions):
[SerializeField] private AnimationClip _Idle;
[SerializeField] private AnimationClip _Walk;
[SerializeField] private AnimationClip _Run;
- Select a Mixer from the Mixer Types table and make a
new
one. For example,new LinearMixerState()
. - Add states to it using a collection initializer or by calling
Add
:
Collection Initializer | Manual Add |
---|---|
|
Saves one line, but takes more code overall. |
- Optionally call
SetDebugName
on the mixer to give it a more descriptive display name to show in the Inspector. - Store a reference to the mixer so you can set its
Parameter
later on to control its blending.
Click here to see an example script which 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 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 after it's created so we can change the Parameter later.
private LinearMixerState _MovementMixer;
protected virtual 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 },
};
// 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);
}
protected virtual 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.
Here's an example of mixer transition nesting:
using Animancer;
using UnityEngine;
public 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 Vector2MixerState _RegularMovement;
private Vector2MixerState _InjuredMovement;
protected virtual void Awake()
{
_Animancer.Play(_MovementMixer);
// Or just create the state if you don't want to Play it yet.
// _Animancer.States.GetOrCreate(_MovementMixer);
_RegularMovement = (Vector2MixerState)_MovementMixer.State.GetChild(0);
_InjuredMovement = (Vector2MixerState)_MovementMixer.State.GetChild(1);
}
protected virtual 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.
Vector2 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 AnimationClip
s.
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 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;
protected virtual 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);
}
protected virtual 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.
Vector2 movement = new Vector2(_MovementX, _MovementY);
_RegularMovement.State.Parameter = movement;
_InjuredMovement.State.Parameter = movement;
}
}