ControllerState
s are a type of State in Animancer which plays a whole Animator Controller where a ClipState
plays a single AnimationClip
. This allows you to fully control how they blend with other animations and can even be used to play multiple Animator Controllers on the same character.
ControllerState
has all the regular Animator
methods you would normally use to control an Animator Controller: Play
, CrossFade
, GetFloat
, SetFloat
, etc.
Transitions
The most common way to set up a ControllerState
is by using a Controller Transition to configure it in the Inspector.
The HybridAnimancerComponent
is actually just a NamedAnimancerComponent
with a ControllerTransition
field and various wrapper methods.
[SerializeField] private AnimancerComponent _Animancer:
[SerializeField] private ControllerTransition _Controller:
[SerializeField] private AnimationClip _SeparateAnimation:
void ControllerTransitionExample()
{
// Play the Animator Controller:
_Animancer.Play(_Controller);
// Set the "MoveSpeed" parameter in the Animator Controller:
_Controller.State.SetFloat("MoveSpeed", 0.5f);
// Play a separate animation not included in the Animator Controller:
_Animancer.Play(_SeparateAnimation);
}
Manual Creation
If you don't want to use a Controller Transition, you can create ControllerState
s yourself using code:
- Get a reference to the
RuntimeAnimatorController
you want to use. - Pass it into a
new ControllerState
. - Store a reference to that state in a field and/or set its Key to register it in the internal dictionary. The
RuntimeAnimatorController
itself or itsname
would make an acceptable key. - Play that state either by passing it into
AnimancerComponent.Play
if you have a reference to it or using the key you registered it with.
[SerializeField] private AnimancerComponent _Animancer:
[SerializeField] private RuntimeAnimatorController _Controller:
[SerializeField] private AnimationClip _SeparateAnimation:
private ControllerState _ControllerState;
void ControllerStateExample()
{
// Create the ControllerState:
_ControllerState = new ControllerState(_Controller);
// Play it:
_Animancer.Play(_ControllerState);
// Fade to it over 0.25 seconds:
_Animancer.Play(_ControllerState, 0.25f);
// Set the "MoveSpeed" parameter in the Animator Controller:
_ControllerState.SetFloat("MoveSpeed", 0.5f);
// Play a separate animation not included in the Animator Controller:
_Animancer.Play(_SeparateAnimation);
}
Parameter Controller States
Animancer includes several classes which inherit from ControllerState
to wrap specific parameters of the AnimatorController
in C# properties:
Float1ControllerState
Float2ControllerState
Float3ControllerState
They also have corresponding Transition Types.
Using them is very similar to the base class, but you also specify which parameter(s) you want to target in the constructor and can then get and set those parameters via their Parameter
properties.
- This has the added benefit of verifying that the parameter actually exists on startup to make it easier to detect bugs.
- Using their Transitions gives you a helpful dropdown menu in the Inspector for selecting the parameter name(s) instead of hard-coding them as Magic Strings. The Linear Mixers sample demonstrates the use of a
Float1ControllerTransition
. - You can easily make your own copies of the scripts containing these classes if you want to adapt them for other parameter types and purposes or you can use the Controller State Generator to create a dedicated class for a specific Animator Controller.
Controller State Generator
Weaver is another Unity Plugin developed by Kybernetik which contains a system for procedurally generating C# scripts (among many other features). It can procedurally generate a class for Animancer which inherits from ControllerState
and contains properties for directly accessing the parameters of a specific Animator Controller asset.
- Download Weaver Lite or Weaver Pro.
- Select the Animator Controller asset you want to generate a class for.
- Open the context menu via the cog icon in the top right of the Inspector and execute the
Generate Controller State
function. - Choose where to save the generated script.
Here is the class it would generate if you used that function on the Humanoid Idle And Move Animator Controller from the Hybrid Character sample:
Note that it has both a state and a parameter called "Move" so the MoveHash
can be used for both of them.
#pragma warning disable // All.
/// <summary>An <see cref="Animancer.ControllerState"/> for the 'Humanoid Idle And Move' Animator Controller.</summary>
public sealed class HumanoidIdleAndMoveState : Animancer.ControllerState
{
#region Hash Constants
/// <summary>Idle</summary>
public const int IdleHash = 2081823275;
/// <summary>Move</summary>
public const int MoveHash = 1326225478;
#endregion
#region Parameter Wrappers
/// <summary>Creates a new <see cref="HumanoidIdleAndMoveState"/>.</summary>
public HumanoidIdleAndMoveState(UnityEngine.RuntimeAnimatorController controller, bool keepStateOnStop = false)
: base(controller, keepStateOnStop)
{
#if UNITY_EDITOR
new Animancer.ControllerState.ParameterID("Move", MoveHash).ValidateHasParameter(controller, UnityEngine.AnimatorControllerParameterType.Bool);
#endif
}
/// <summary>The value of the 'Move' parameter in the Animator Controller.</summary>
public bool Move
{
get => Playable.GetBool(MoveHash);
set => Playable.SetBool(MoveHash, value);
}
/// <summary>ParameterCount</summary>
public override int ParameterCount
{
get => 1;
}
/// <summary>GetParameterHash</summary>
public override int GetParameterHash(int index)
{
switch (index)
{
case 0: return MoveHash;// Move.
default: throw new System.ArgumentOutOfRangeException(nameof(index));
}
}
#endregion
#region Transition
/// <summary>A serializable <see cref="Animancer.ITransition"/> which can create a <see cref="HumanoidIdleAndMoveState"/> when passed into <see cref="Animancer.AnimancerLayer.Play(Animancer.ITransition)"/>.</summary>
[System.SerializableAttribute]
public new class Transition : Transition<HumanoidIdleAndMoveState>
{
/// <summary>Creates and returns a new <see cref="HumanoidIdleAndMoveState"/>.</summary>
public override HumanoidIdleAndMoveState CreateState() => State = new HumanoidIdleAndMoveState(Controller, KeepStateOnStop);
#if UNITY_EDITOR
/// <summary>[Editor-Only] Draws the Inspector GUI for a <see cref="Transition"/>.</summary>
[UnityEditor.CustomPropertyDrawer(typeof(Transition), true)]
public new class Drawer : Animancer.ControllerTransition.Drawer
{
}
#endif
}
#endregion
}
The source code of the generator script is located at Assets/Plugins/Weaver/Procedural Assets/Animations/ControllerStateGenerator.cs.
Generating Transitions
If you have an Animator Controller which you want to replace with Animancer, you can select any of its states and use the cog icon in the top right of the Inspector to execute the Generate Transition
function which will create Animancer Transition Assets for each of those states:
- A regular state will create a
ClipTransition
. - A Blend Tree will create an equivalent Mixer State depending on its Blend Type according to the Choosing a Mixer table.