Using Blender and Rigify
Creating custom animation Playables

Playable API

The Unity Script Reference (API) provides a way to create tools, effects and other gameplay mechanisms by organizing and evaluating data sources in a tree-like structure. This tree-like structure lets you mix, blend and modify multiple data sources and play them through a single output. The Playable API supports animation graphs, so you can interact with animation via scripting.

Note that the Playable API is part of the “experimental” namespace, and that scripts created with it might not be compatible with future versions of Unity.

If you have used Playable API in versions before 5.4 you should check the Upgrade Guide for details of migrating to 5.4.

How to use

Playing a single clip on a GameObject

The following MonoBehaviour creates a simple tree with a single node, which plays a single clip.

The AnimationClipPlayablewraps an AnimationClip to make it compatible with the Playable API.

The Play() operation connects the Playable with the Animator so the root of the graph (in this case the AnimationClipPlayable) can be played.

using UnityEngine;
using UnityEngine.Experimental.Director;
 
[RequireComponent (typeof (Animator))]
public class PlayAnimation : MonoBehaviour
{
    public AnimationClip clip;
 
    void Start () 
    {
        // Wrap the clip in a playable
        var clipPlayable = AnimationClipPlayable.Create(clip);
 
        // Bind the playable to the player
        GetComponent<Animator>().Play(clipPlayable);
    }

}

Creating an animation blend tree through code

The AnimationMixerPlayable blends two or more AnimationClipPlayables, or can blend other mixers, which themselves blend other clips, etc. The SetInputs() method creates the underlying AnimationClipPlayable nodes implicitly (this method can also take an array of AnimationPlayables directly).

The weight of each clip in the blend is adjusted dynamically via SetInputWeight(), creating a blend tree that smoothly changes from one animation to the other over time.

using UnityEngine;
using UnityEngine.Experimental.Director;
 
[RequireComponent (typeof (Animator))]
public class MixAnimation : MonoBehaviour
{
    public AnimationClip clip1;
    public AnimationClip clip2;
 
    private AnimationMixerPlayable m_Mixer;
 
    void Start () 
    {
        // Create the mixer and connect it to clips
        // (AnimationClipPlayables are created implicitly)
        m_Mixer = AnimationMixerPlayable.Create();
        m_Mixer.SetInputs(new[] {clip1, clip2});
 
        // Bind the playable graph to the player
        GetComponent<Animator>().Play(m_Mixer);
    }
 
    void Update()
    {
        // Adjust the weight of each clip in the blend tree based on time
        float weight = (Time.time % 10) / 10;
        m_Mixer.SetInputWeight(0, weight);
        m_Mixer.SetInputWeight(1, 1 - weight);
    }
}

Blending the AnimatorController

Just as the AnimationClipPlayable wraps an AnimationClip, the AnimatorControllerPlayable wraps an AnimatorController so you can blend them with other AnimationPlayables.

using UnityEngine;
using UnityEngine.Experimental.Director;
 
[RequireComponent (typeof (Animator))]
public class BlendAnimatorController : MonoBehaviour
{
    public AnimationClip clip;
    public RuntimeAnimatorController animController;
 
    void Start () 
    {
        // Wrap the clip and the controller in playables
        var clipPlayable = AnimationClipPlayable.Create(clip);
        var controllerPlayable = AnimatorControllerPlayable.Create(animController);
        var mixer = AnimationMixerPlayable.Create();
        mixer.SetInputs(new Playable[] {clipPlayable, controllerPlayable});
        
        // Bind the playable graph to the player
        GetComponent<Animator>().Play(mixer);
    }
}

Controlling the timing of the tree manually

By default, the Play() method on the PlayableController handles all the timing of the tree playback. However, for additional control, you can explicitly set the local time of a Playable. This local time will be passed on to child nodes.

In this example you can pause the playback, and advance and rewind the animation manually using the keyboard arrows.

using UnityEngine;
using UnityEngine.Experimental.Director;
 
[RequireComponent (typeof (Animator))]
public class PlayWithTimeControl : MonoBehaviour
{
    public AnimationClip clip;
 
    private Playable m_Root;
    private const float k_SpeedFactor = 1f;
 
    void Start () 
    {
        m_Root = AnimationClipPlayable.Create(clip);
        
        // Bind the playable to the player
        GetComponent<Animator>().Play(m_Root);
 
        m_Root.state = PlayState.Paused;
    }

    void Update () 
    {
        // Control the time manually based on the input
        float horizontalInput = Input.GetAxis("Horizontal");
        m_Root.time += horizontalInput * k_SpeedFactor * Time.deltaTime;
    }
}

Controlling the play state of the tree

You can set the state of the tree, or a branch of the tree, by changing the Playable.state parameter. This state will pass to all children of the node, regardless of their previous state. If a child node was explicitly paused, setting a parent to the Playing state will also set the child to the Playing state.

Using Blender and Rigify
Creating custom animation Playables