Search Unity

Wayne Johnson and I have presented the Playable API at GDC 2016 and we would like to share with you what we have talked about.

The Playable is a new graph-like API in Unity that allows to have precise programmatic control over Animation and Audio. We are also planning on having video use the same API.

Please be aware that the API is still experimental as we are still working on making it very slick and easy to use. The examples provided here work with Unity 5.4. We expect that there will be changes in the API again before it’s integrated into one of our future releases. Keep an eye on our Roadmap for updates.

The simple case : Playing a clip.

One of the main goals of the playable system is to make sure simple things are simple to do. So let’s start with the basics and play a clip.

Easy ? Now, we can control time and speed simply like this:

 

 

A step further : Creating a dynamic Blend Tree

BlendTrees allow to blend animation values between different AnimationClips or even between other BlendTrees. Mecanim’s BlendTrees are quite powerful, but they need to be built in the Editor. With Playables, it’s now possible to create and control BlendTrees at runtime. We can do that using the AnimationMixerPlayable:

Then, we control the weights using:

Pro Tip : make sure the sum of the weights is 1.0f.

Custom Playable : Crossfade

image02

While designing the Playable API, one of our key goals was for the system to be extensible. The CustomAnimationPlayable allows you to write your own Playable logic. The secret sauce here is the PrepareFrame callback that automatically gets called when the Playable graph is traversed by the game loop. PrepareFrame is where the blending/weighting logic of the CustomPlayable happens.

In the following example, we implemented a CrossFade Playable that looks and behaves a lot like the Legacy animation system’s CrossFade:

 

We are also working on another callback for the CustomPlayable which will be ProcessFrame. In the case of animation, this will allow to write directly into the animation stream and will give users the power to have their own IK, procedural animation, physic based system, live Mocap etc…

Putting it all together with AnimatorControllerPlayable

Another very nice thing about the API is that you can actually have AnimatorControllers in your graphs. Yes! This means that you can blend between StateMachines! This allows objects and props to supply their own animation StateMachine.

For instance, let’s say you have a weapon and you want the weapon to “teach” the player how to use it. The weapon will provide the AnimatorController (StateMachine) to the Player and will ask to crossfade to it.

 

The CharacterPlayableHandler is a simple interface over a CrossFade Playable.

Seeing is believing

It’s very important to be able to visualize the Playable graphs during runtime. In order to do so, we have created the GraphVisualizer, an open source editor-suite that allows previewing Playable graph.

You can download it right now from BitBucket at https://bitbucket.org/Unity-Technologies/playablegraphvisualizer.

There are examples included and it’s very very simple to use!

So what about audio ?

During the GDC Dev Day talk we also presented a Playable API for audio, which works in a similar way as the current Animation Playable API.

The API allows a very powerful, low level control of audio concepts within Unity. It will not only allow programmers to do new and interesting things with Audio in Unity, but will also serve as the foundation of future audio tooling in the Editor.

We would have liked to have presented a section outlining code examples for Audio Playables, however this API is currently in flux and will not be present in the 5.4 release cycle.

We’re looking forward to showing you the Audio Playables once we have finalised the API!

That is it for now!

We hope this gets you excited about Playables. As we said, this is still stuff we are working on, there are a couple of things that we want to change and improve on before we move it out of the experimental stage.

So please, try it and tell us what you think about it!

21 Comments

Subscribe to comments

Comments are closed.

  1. Time.time give seconds so weight resolution is to rough when for example animationClip is in total 2s, so if we assume Prepare frame is called in FPS times. Also shifting port while playing might cos glitch. Have fun!

    namespace ws.winx.unity.components {
    public class CrossFadeMixerPlayable : CustomAnimationPlayable {

    private float m_TransitionDuration = 1.0f;
    private float m_TransitionTime = 0.0f;
    private float m_TransitionStart = 0.0f;

    private bool m_InTransition = false;

    private AnimationMixerPlayable mixer;

    private enum FreePort {
    PORT0 = 0,
    PORT1
    }

    private FreePort __freePort;

    private float __frameDuration;

    public CrossFadeMixerPlayable() {

    mixer = AnimationMixerPlayable.Create();
    Playable.Connect(mixer, this);
    mixer.AddInput(Playable.Null);
    mixer.AddInput(Playable.Null);
    __freePort = FreePort.PORT0;
    }

    public void Play(AnimationClipPlayable animationClipPlayable) {
    this.Crossfade(animationClipPlayable,0f);
    }

    ///
    ///
    ///
    ///
    /// in sec
    /// (default)30
    public void Crossfade(AnimationClipPlayable animationPlayable, float transitionDuration, int frameRate = 30) {

    m_TransitionTime = 0.0f;
    __frameDuration = 1f / frameRate;

    Playable playable = mixer.GetInput((int)__freePort);

    if (playable != Playable.Null) {
    playable.time = 0f;
    playable.state = PlayState.Paused;
    Playable.Disconnect(mixer, (int)__freePort);
    }

    //Connect to free port
    Playable.Connect(animationPlayable, mixer, 0, (int)__freePort);
    animationPlayable.time = 0f;
    animationPlayable.state = PlayState.Playing;

    //UPGRADES
    //make dynamic transition value equal duration of current playable to finish???
    //transitionDuration=(1f-(float)(playable1.time-(int)playable1.time))*playable1.CastTo().clip.length;
    //if this duration is longer then new playable then shift start of transition for the amount of difference

    if ( __freePort == FreePort.PORT0) {

    __freePort = FreePort.PORT1;
    } else {

    __freePort = FreePort.PORT0;
    }

    m_TransitionDuration = transitionDuration;

    m_InTransition = true;

    Debug.Log("Time at start:" + m_TransitionTime + " duration:" + m_TransitionDuration);

    }

    public override void PrepareFrame(FrameData info) {

    if (m_InTransition) {
    if (m_TransitionTime <= m_TransitionDuration)
    {
    m_TransitionTime += __frameDuration;// Time.time - m_TransitionStart;
    float weight = Mathf.Clamp01(m_TransitionTime / m_TransitionDuration);

    mixer.SetInputWeight(1 - (int)__freePort, weight);

    mixer.SetInputWeight((int)__freePort, 1.0f - weight);

    Debug.Log("Transition time update:" + m_TransitionTime);
    }
    else
    {

    mixer.RemoveInput((int)__freePort);

    m_InTransition = false;

    Debug.Log("Transition end at:" + m_TransitionTime);
    }

    Debug.Log(this.ToString());
    }

    }

    public override string ToString() {
    string info = string.Empty;

    info += " crossfade layer mixer time:" + mixer.time;

    for (int i = 0; i < mixer.inputCount; i++) {
    Playable playable = mixer.GetInput(i);

    if (playable != Playable.Null) {
    info += "\n Port:" + i + " State:" + playable.state + " time:" + ((float)(playable.time - (int)playable.time)) + " weight:" + mixer.GetInputWeight(i) + " clip:" + playable.CastTo().clip;
    } else {
    info += "\n Port:" + i + " Empty!";
    }
    }

    return info;
    }

    }
    }

  2. AnimationLayerMixerPlayable could you bring the light of this sealed type?

  3. All this hassle and we don’t even have a proper tween engine, Mecanim is a big fail, making once simple things overly complicated.

    1. Unfortunately you are right. Bad decision was made by making Mecanim animation specific FSM,instead general, those breaking the connection with rest of the logic, and without API that ofter extra animation control by code. Soon when more control was obviously needed, they patch it with StateBehaviours. StateBehaviours are inside asset and bit difficult to communicate with GameObjects on Scene, and old school in Unity avoid UnityEvents. If you had follow @pierrpaul have mention “Legacy” 2x times on GDC and even in this text “that looks and behaves a lot like the Legacy”, so it is obvious where things are going.

  4. Is it possible to use AvatarTarget with Playables?
    What is the progress of Video Playables?

    1. * AvatarMask and layers in Playables

  5. It’s great !

    Something I would like to see, and I desperately need is to play just a section of a clip.
    I have an object with an animation of 800 frames, that I need to cut into 100 frames clips at runtime.

    So maybe something like:
    AnimationClip clip ; // assign to your clips
    AnimationClipPlayable playable = AnimationClipPlayable.Create(clip, 0, 100); //StartFrame, EndFrame
    GetComponent().Play(playable);

    1. That is interesting!

      Not sure if its requested enough to be added the the API, but the good thing is that it’s fairly easy to implement this with a CustomPlayable, simply handle the time directly in PrepareFrame.

  6. In the latest versions of unity i can’t export stable apk file to run on android devices.
    program force closed appear in most of devices ! even don’t show unity splash screen !

  7. We hope this gets you excited about Playables.

    Lets see… So you need 2 lines of code to “simple play a clip” instead of one. Mkay…

    And then you need 50 lines of code to replicate a cross fade that has been in Unity since years. uhu….

    The visualizer (note: Not an editor, only visualizer) looks very basic. And we already have not only a visualizer, but an whole editor for animation graphs (Mecanim, of course).

    Finally comes the part with the new stuff like audio and video… oh, wait. Its not here. Just an announcement.

    So am I excited? No, not really. There is nothing here that is new – compared to the very first presentation about the API from around half a year ago..

    1. This really isn’t something that replaces Mecanim; it complements it.

      With playables you can tell an actual AnimationController to play a clip directly, which wasn’t possible before (only possible with legacy). You can also determine exactly how crossfading will work (based on any sort of curve or parameter you want). You can crossfade between state machines too.

      This unlocks so many possibilities for animation.

      1. Be careful to not become an architectural astronaut. If you make an universal uber-framework, be sure to at least show practical cool things of what you can do.

        Showing something in 50 lines of code that is solved for years and everybody takes for granted is the worst thing you can present to get people excited.

        There are so much things you could show that are currently “not so easy” or even impossible. What about a fully standard animated character running around in typical Mecanim-2D-BlendTree fashion (as seen in all the tech demos). And then you slightly blend in some electrocuted animation – regardless of the current mecanim state he is in. Works in all states.

        Or what about procedural generated animation? Or Physics blending with Animations?

        1. Hi.

          As I explain a little bit in the post, we want to give you guys access to the “animation feed”. Meaning that with CustomPlayable you will have a function that is called ProcessFrame and that will allow to do all sorts of procedural animation ( IK, Mocap, pull system, physic integration etc..). Its not ready yet but I hope to post something here as soon as I get something worth showing :)

  8. Fernando17Bmoney

    April 15, 2016 at 6:48 am

    Hey where can buy this asap will this let me do my own soundtrack like to sound 2d arcady sound and upload my own samples? Will i be able to make movie clips on the game

  9. Looks awesome, and I can’t wait for this to be officially released.

    It’s great that you guys are making some of the engine’s systems more open to allow us to come up with our own solutions if we need to.

  10. Any plans to have forward and backward controls for Movie textures clips? Was hoping that would also be included

  11. This looks very promising.

  12. “We are also planning on having video use the same API.”

    This actually catches my attention, since the whole movie texture system needs defiantly an overhaul. Does this mean, we’ll get video support for: mobile and vr as well without launching external players? As now you’re bound to use plugins on which you depend if the creator continues development. Especially now with VR, video is a big things but native support is a huge problem.

    However, rest of the article is interesting as well. I was just curious about video, since last year Unite, promises were made to improve it.

    1. We are in the process of overhauling our video support to properly utilise hardware decoding capabilities of mobile and other devices. This will make high resolution video playback on mobile devices possible, including for VR applications.

      To begin with we will roll out these video improvements as they become stable. From there we will integrate video concepts into the Playable framework to allow a low level API to video compositing.

  13. Will this work with the Legacy animation system? I’m never going to be able to use Mecanim due to my rig’s IK structure.

    1. I don’t see why Mecanim would cause you troubles for that. If you want custom IK with mecanim, simply run your mecanim animations normally, and then make an IK script that processes IK on LateUpdate()

      LateUpdate() happens right after the new animation pose has been computed, but right before the scene is rendered