Controller States

ControllerStates 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 ControllerStates yourself using code:

  1. Get a reference to the RuntimeAnimatorController you want to use.
  2. Pass it into a new ControllerState.
  3. 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 its name would make an acceptable key.
  4. 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.

  1. Download Weaver Lite or Weaver Pro.
  2. Select the Animator Controller asset you want to generate a class for.
  3. Open the context menu via the cog icon in the top right of the Inspector and execute the Generate Controller State function.
  4. 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: