Parameters

Animancer Parameters are strongly typed, named values stored in a central dictionary for scripts to get, set, and watch for changes.

  • Mixer States and Controller States can link their internal parameters to Animancer Parameters so that:
    • Other scripts can control their values without needing direct access to the states.
    • Multiple states can be linked to the same parameter.
    • The Linear Mixer sample demonstrates this feature in action.
  • The dictionary uses String References as its keys.
  • A parameter of any type can be created, but it can then only contain values of that type.

Cached Example

The most efficient way to access frequently used parameters is to store them in a Parameter<T> field, where T is the Generic Argument specifying the type of value it will contain.

public class CachedParameterExample : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private StringAsset _ParameterName;

    private Parameter<float> _Parameter;

On startup, you access the AnimancerComponent.Parameters dictionary to GetOrCreate the parameter you want, meaning that whatever system access a parameter with a particular name first will create it then any other system to use the same name will be given the same parameter.

    protected virtual void Awake()
    {
        _Parameter = _Animancer.Parameters.GetOrCreate<float>(_ParameterName);

Then you can listen for any changes to the parameter using its OnValueChanged event.

        _Parameter.OnValueChanged += OnParameterChanged;
    }

    private void OnParameterChanged(float value)
    {
        Debug.Log(value);
    }

Or get and set its Value whenever you want.

    protected virtual void Update()
    {
        _Parameter.Value = Time.timeSinceLevelLoad;
    }
}

Lazy Example

You can also interact with parameters in the dictionary instead of caching them in a field. This can simplify the code, but is less efficient if it needs to look up the parameter every time.

If the above example wasn't setting the Value and only needed to listen for OnValueChanged, it could use AddOnValueChanged without losing any efficiency.

public class LazyParameterExample : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private StringAsset _ParameterName;
    
    protected virtual void Awake()
    {
        _Animancer.Parameters.AddOnValueChanged<float>(_ParameterName, OnParameterChanged);
    }

    private void OnParameterChanged(float value)
    {
        Debug.Log(value);
    }

It could also use SetValue, but doing that every frame in Update would be inefficient because it needs to internally find the parameter from the name every time. Dictionaries allow for fast lookups, but they're still slower than keeping a direct reference.

    protected virtual void Update()
    {
        _Animancer.Parameters.SetValue(_ParameterName, Time.timeSinceLevelLoad);
    }
}

Smoothing

Changing a parameter value takes effect immediately, so if you want it to change gradually over time you can use a SmoothedFloatParameter or SmoothedVector2Parameter as demonstrated in the Directional Mixer and Brains samples.

public class ParameterSmoothingExample : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private StringAsset _Parameter;
    [SerializeField] private float _ParameterSmoothTime = 0.15f;

Initializing a SmoothedFloatParameter takes the AnimancerComponent containing the parameter, a String Reference or Asset to specify its name, and the approximate amount of time you want it to take to reach the target value using the internan Mathf.SmoothTime.

    private SmoothedFloatParameter _SmoothedParameter;

    protected virtual void Awake()
    {
        _SmoothedParameter = new SmoothedFloatParameter(
            _Animancer,
            _Parameter,
            _ParameterSmoothTime);
    }

You can then set the TargetValue on the smoother or simply set the parameter value normally to have it smoothly move towards that value.

    protected virtual void Update()
    {
        _SmoothedParameter.TargetValue = 0;

        _Animancer.Parameters.SetValue(_Parameter, 0);

Or you can set the CurrentValue to move it immediately and cancel any active smoothing.

        _SmoothedParameter.CurrentValue = 0;
    }
}

Using SmoothedVector2Parameter is the same as all that, except it takes two parameter names in the constructor and the value is a Vector2.

Debugging

Since this system is designed to be accessed from anywhere, it's unfortunately easy to end up in situations where parameters are given unexpected values. That's why there's an inbuilt logging system which can be turned on for a particular parameter to log any time something gets or sets its value as well as any OnValueChanged listeners that are added or removed.

How to enable parameter logging

Logging can be enabled via the Inspector or via code.

In the Live Inspector you can Right Click on a parameter and select the Log Interactions function from the Context Menu.

In code, you can set the parameter's LogContext like this:

public class DebuggingParameterExample : MonoBehaviour
{
    [SerializeField] private AnimancerComponent _Animancer;
    [SerializeField] private StringAsset _ParameterName;

    private Parameter<float> _Parameter;

    protected virtual void Awake()
    {
        _Parameter = _Animancer.Parameters.GetOrCreate<float>(_ParameterName);
        _Parameter.LogContext = this;
    }
}

You can assign any type of object as the context such as a component or string and it will be used as a prefix for that parameter's log messages in case you need to debug multiple parameters at the same time.

When is this logging available

By default, this logging is available in the Unity Editor and in Development Builds, but not regular Release Builds.

If you need to use it in a Release Build you can define ANIMANCER_DEBUG_PARAMETERS as a Custom Scripting Symbol in your project. Unfortunately, this requires Animancer Pro as the scripts need to be recompiled with that symbol active which can't happen with the pre-compiled DLLs in Animancer Lite.

Inspector Control Only

It can also sometimes be useful to prevent all scripts from setting a parameter so that you can control it manually in the Inspector and observe the effects.

This can be done by enabling Inspector Control Only via the same context menu as explained above or in code by setting the _Parameter.InspectorControlOnly = true;.