Skip to main content

Animator Parameters

Direct Buffer Indexing

Rukhanka made DynamicBuffer for all animator parameters so the user can control its values from the code.

Basically, only DynamicBuffer with animator parameters is needed to access and manipulate parameter values. This is shown in the following code snippet:

[BurstCompile]
partial struct ProcessInputJob: IJobEntity
{
void Execute(ref DynamicBuffer<AnimatorControllerParameterComponent> allParams)
{
var someParameter = allParams[0];
// Increment parameter
someParameter.FloatValue += 1.0f;
// Put value back in the array
allParams[0] = someParameter;
...
}
}

This approach has only one advantage: access speed. Animator parameters are ordered in a way how they are defined in Unity's Animator from top to bottom. For example, in Animator parameters given in the next picture, there are three parameters: [0] - "Blend", [1] - "Run Speed", [2] - "InAir":

Animator Parameters Ordering

Accessing by Hash

Accessing parameters by index has no name-value relationship. Any animator parameter reordering in Animator Controller will break the game logic code. So there is a better solution: accessing using a hash table. Rukhanka prepares Perfect Hash Table for a list of parameters during the baking stage. A perfect hash table is a hash table that has an unambiguous 'parameter name' -> 'array index' relationship. It is faster than ordinary hash tables and also has O(1) access complexity.

To simplify access to the parameters, the helper class named FastAnimatorParameter and AnimatorParametersAspect aspect were introduced. Follow these steps to access the animator parameter by name and in a very performant way:

  • Define required FastAnimatorParameters as, for example, system private fields:

    public partial class PlayerControllerSystem: SystemBase
    {
    FastAnimatorParameter blendParam = new FastAnimatorParameter("Blend");
    FastAnimatorParameter runSpeedParam = new FastAnimatorParameter("RunSpeed");
    FastAnimatorParameter inAirParam = new FastAnimatorParameter("InAir");
    ...
    }
  • Pass prepared FastAnimatorParameters in the job:

    protected override void OnUpdate()
    {
    var processInputJob = new ProcessInputJob()
    {
    blendParam = this.blendParam,
    runSpeedParam = this.runSpeedParam,
    inAirParam = this.inAirParam
    };

    ...
    }
  • Query AnimatorParametersAspect and use the FastAnimatorParameter methods to access parameter value:

    [BurstCompile]
    partial struct ProcessInputJob: IJobEntity
    {
    public InputStateData inputData;

    public FastAnimatorParameter floatParam;
    public FastAnimatorParameter intParam;
    public FastAnimatorParameter triggerParam;
    public FastAnimatorParameter boolParam;

    void Execute(ref AnimatorParametersAspect paramAspect)
    {
    paramAspect.SetParameterValue(floatParam, 2.2f);
    paramAspect.SetParameterValue(intParam, 42);
    paramAspect.SetParameterValue(boolParam, true);
    paramAspect.SetTrigger(triggerParam);

    var floatValue = paramAspect.GetFloatParameter(floatParam);
    var boolValue = paramAspect.GetBoolParameter(boolParam);
    }
    }

Some functions of AnimatorParametersAspect accept FixedString with parameter names. Those variants are slower than with FastAnimatorParameter and created mostly for easiness of quick prototyping and should not be used in final high performance code.