Animator Access Generator For Unity

Posted by on in Development-Blog
  • Font size: Larger Smaller

This video gives a quick overview of Animator Access Generator, a C# code generator that makes handling of Animator states and parameters easier:

  • You don't have to enter state or parameter names manually any longer as they will be generated automatically.
  • Register event handlers on state changes or transitions that met predefined conditions.
  • Using it will let the compiler detect most possible problems in your code, saving you time consuming bug analysis because of wrong hash IDs.

 

 

Most important features:

  • Defines public member variables to hold the hash IDs of all Animator states and parameters and initialises them in Awake () with the correct name string constants
  • Query Animator states by using explicit methods e.g.
    bool IsIdle () for checking a state named Idle
  • Provides dedicated methods for accessing every parameter e.g. 
    void SetSpeed (float newValue) and float GetSpeed () for setting a float parameter speed
  • Register event handlers to be called on Animator state changes or transtions e.g.
    anim.TransitionTo (anim.stateIdWalking).OnStarted += OnStartedTransitionToWalking;
    anim.State (anim.stateIdIdle).OnActive += OnIdle;
  • Easy to use through custom editor for AnimatorAccess components
    Animatior Access Custom Editor
  • Supports smooth updates on name changes by analysing the existing class's code and marks outdated members as obsolete first. They will not be removed before the code is generated one more time
  • Customise the way how variable and method names are built

Resources

Animator Access Generator is an open source project hosted at GitHub see:

 

Code Sample

Excerpt of generated code (see ExamplePlayerAnimatorAccess.cs for full code):

public class ExamplePlayerAnimatorAccess : BaseAnimatorAccess
{
    /// <summary>
    /// Hash of Animator state Base Layer.Idle
    /// </summary>
    public int stateIdIdle;
    // ...
    public int paramIdSpeed;
    public int paramIdJumpTrigger;
    // ...
    
    public void Awake () { 
        animator = GetComponent<Animator> ();
        // ...
    }
    public override void InitialiseEventManager () {         
       
StateInfos.Add (-2010423537new StateInfo (-20104235370
           
"Base Layer""Base Layer.Walking"""1ffalsefalse"Walk"));
        // ...
        TransitionInfos.Add (708569559new TransitionInfo (708569559
           
"Base Layer.Walking -> Base Layer.Idle",
.
        // ...
    }
   
public bool IsIdle () { 
        return stateIdIdle == animator.GetCurrentAnimatorStateInfo (0).nameHash;
    }
    // ...
    public void SetSpeed (float newValuefloat dampTimefloat deltaTime) {         
       
animator.SetFloat (paramIdSpeednewValuedampTimedeltaTime);
    }
    public void SetSpeed (float newValue) { 
        animator.SetFloat (paramIdSpeednewValue);
    }
    public float GetSpeed () {
        return animator.GetFloat (paramIdSpeed);
    }
    public void SetJumpTrigger () { 
        animator.SetTrigger (paramIdJumpTrigger);
    }
    // ...
}

Using generated code (see Player.cs for full code): 

using AnimatorAccess;

public class Player : MonoBehaviour
{
    ExamplePlayerAnimatorAccess anim;       
    Animator animator;
    int currentState0;
    public float speed;
    public float maxSpeed = 5f;
    float horizontalInput;
    bool jumpKeyPressed = false;
        
    void Awake () {
        animator = GetComponent<Animator> ();
        anim = GetComponent<ExamplePlayerAnimatorAccess> ();
    }
        
    void OnEnable () {
        anim.State (anim.stateIdIdle).OnActive += OnIdle;
        anim.State (anim.stateIdJumping).OnEnter += OnEnterJumping;
        anim.TransitionTo (anim.stateIdWalking).OnStarted += 
                
OnStartedTransitionToWalking;
    }

    void OnDisable () {
         anim.OnStateChange -= OnStateChange;
    }
    void OnStartedTransitionToWalking (TransitionInfo infoLayerStatus status) {
         Debug.Log ("Called when any transiton with target walking is starting");
    }

   
void OnIdle (StateInfo infoLayerStatus status) {
        Debug.Log ("OnIdle: called every frame while in state idle");
    }
    void OnEnterJumping (StateInfo infoLayerStatus status) {
        Debug.Log ("OnEnterJumping: Jump, called once ");
    }

   
void Update () {
        horizontalInput = Input.GetAxis ("Horizontal");
        jumpKeyPressed = Input.GetKeyDown (KeyCode.UpArrow);
    }
        
    void FixedUpdate () {
        if (anim.IsJumping ()) {
            // alternatively use polling to check for state changes instead of events
        }
        if (jumpKeyPressed) {
            anim.SetJumpTrigger ();
        }
        speed = horizontalInput * maxSpeed;
        anim.SetSpeed (Mathf.Abs (speed));
        // alternative (not recommendedway of accessing hash IDs directly:
        // animator.SetFloat (anim.paramIdSpeedMathf.Abs (speed));
    }
}

 

 

Submit to FacebookSubmit to TwitterSubmit to LinkedIn
Rate this blog entry:

Comments

  • No comments made yet. Be the first to submit a comment

Leave your comment

Guest Donnerstag, 29 Juni 2017

Zusätzliche Informationen