How are we supposed to create custom Playables for Timeline?

I am trying to create a dialog box Playable to show dialog boxes in cutscenes. I’ve downloaded an example project called TimelineCinemachine_GameplayMarketDemo, which has a simple dialog box Playable, which uses just one script on the Timeline, called ConversationPlayable.
However, I’ve also been watching the Unity video, “Unite Europe 2017 - Extending Timeline with your own playables”, with James Bouckley, and he’s using the Default Playables Package from the Asset Store, and he’s using 4 scripts to create a Playable: Clip, Mixer, Behavior, and Track scripts. And he said that’s probably going to change in the near future.
And the Unity Manual says to use ScriptPlayable and PlayableBehaviour.
I’m not sure what methodology I’m supposed to be using. Anyone have any insight? The 4 scripts method seems very confused to me.

My interpretation is that the Default Playables wizard may change, but the structure of the 4 scripts will remain the same. So any scripts generated by the wizard should still continue to work in the future. (I could be wrong.) In any case, it was fairly inscrutable to me, too, until I let the wizard generate as much of the scripts as possible. At that point, it was fairly easy to fill in my code where indicated.

You can safely use Clip, Mixer, Behavior, and Track scripts to extend Timeline. James said that this is going to change because we are looking to make it easier for users to extend Timeline; we may add new classes but we do not plan to deprecate the existing classes.

Let’s have a look at the 4 classes that you can inherit from in order to extend Timeline:
-Clip: In order to extend a clip, you need to derive from two classes: PlayableAsset and PlayableBehaviour. The PlayableAsset will contain the data and the PlayableBehaviour will execute something based on the asset’s data. ScriptPlayable is only used to instantiate a new PlayableBehaviour.

  • Track: To extend a track, you need to inherit from TrackAsset
  • Mixer: A mixer needs derive from PlayableBehaviour. You can specify the type of mixer in TrackAsset.

This is correct.

So I guess the wizard and it’s four classes are for more extensive work, like making your own custom Tracks.

Otherwise, I can just derive from PlayableBehavior and PlayableAsset as necessary to put something like a dialog box controller on the timeline. Is this correct?

The wizard just creates the boilerplate code for you. You can always bypass the wizard and create new classes that derive from PlayableBehaviour and PlayableAsset yourself.

Yeah, but the boilerplate code for what? That's what I don't understand. The wizard seems to be creating boilerplate code for more complicated scenarios than creating a PlayableBehavior to put on the timeline.

The boilerplate code generates four classes (+ an optional UI class).
- PlayableAsset and PlayableBehaviour for clips
- TrackAsset and PlayableBehaviour for tracks.

The asset is the serialized object that represents the track or the clip. The PlayableBehaviours are the runtime classes that represent the instance of that timeline (i.e. the playables).

At a minimum, you need a playable asset and a playable behaviour to add clips to the playable tracks.

can anyone point me in the right direction (documentation, videos) to how and what all those things means? playable assets, playable behaviours? I've been working with unity for around 5 years now and I just updated from 5.6 to 2017.2 to try timeline, but I have no clue what all these names and classes represent exactly, I was able to play around with timeline to do normal stuff like draging animations, cinemachine blends of virtual cameras, play audios, animate exposed fields from X monobehaviours, but I want to take further control and use its complete potential, I understand that you can create custom stuff which then can be driven by timeline, but I don't know the stuff going on under the hood.

for example, I want to animate a generic creature, so far what I did is create a navigation agent with a script that sets its destination to the position of a gameobject, then in timeline I move this gameobject. this way I decouple timeline animation of the target position from the actual creature, allowing me to spawn any random creature model independently of timeline.
otherwise, if I wanted to control the specific 3D model's position with timeline, then I would not have the possibility to switch to another model with another animator controller at runtime, because the reference to the model is unique and not generic.

if anybody understood what I'm trying to say, I can use some help, I want to make things more generic, like timeline animating a destination, animating a generic "blend whatever you are doing now with an attack animation clip" without explicitly dragging the attack clip into timeline, because that will only work for a specific model.

PS: also I'm wondering how you can move/offset all tracks and clips in timeline, I need to make some space at the first seconds to add another camera shot, but I already did lots of works on timeline and manually moving everything is a pain.

thanks!

Maybe a more accurate term for a Timeline Clip, is Item. As Timeline tracks can be used to control most any item, not just animation or audio clips.

Is the Mixer mandatory? Mixer and Clip both inherit from PlayableBehavior. I have been creating clips from the track, and the ProcessFrame seems properly called. Also I’m not sure to understand how a Mixer can get several inputs. I looked at the LightControl example (default playable) but there is only one input.

Wondering about the mixer as well. For example I am trying to create something simple that doesn't need to blend between two clips. Each clip would be completely separate.

Honestly this Timeline stuff is so far proving to be the most confusing thing I've done in Unity.

Then you don’t need a mixer.

Yes, timelines structure is confusing. It’s not the same paradigm as writing a Monobehaviour.

Timeline is authored using Scriptable Objects (TimelineAsset, TrackAssets and PlayableAssets). They act as assets.

These get compiled into a PlayableGraph when an instance of the timeline is needed. This allows one asset to be have several instances running. Using the Playable system means an instance is more performant, uses less memory and is compatible with other systems (Animation, Audio, with Video and others on the way).

The PlayableAsset represents custom data for a timeline clip. The Playable Behaviour is an instance of the clip.

A TrackAsset represents the track. A mixer is a PlayableBehaviour that represents the instance of the track, and is only needed if you need to define how clips are blended or you are writing a final result to a binding, such as a component.

For example, for a custom track that writes text on a screen would have
A PlayableAsset that defines and serializes what data is needed for a clip (e.g. a string and a color)
A PlayableBehaviour that is an instance of that data, and possibly does any modification of that data required at runtime. (e.g. does a localization translate)
A custom TrackAsset. It would be the container for clips of that data, and defines

  • It holds clips that support text
  • What mixer to use
  • What the track binds to (e.g. a UI Text component)
    A Mixer (PlayableBehaviour) that determines how those clips should blend. For example, the colours could blend, and the text could fade. It will also write the the final result to the text component.

There are several improvements we have been looking at to make this easier. The content team has some example on the asset store here, including a wizard that will generate the necessary boilerplate code.

I hope that helps clarify it.

1 Like

Thanks for the precisions. I still have few questions.
Let's say I don't use a mixer, just PlayableBehavior. Is it normal that ProcessFrame is always called? How can I know that there is no clip at this frame? info.weight is always = 1...
Now if I use a mixer, playable.GetInputCount () is always equal to the number of clips. So I have to check that all playable.GetInputWeight(i) = 0 in order to determine that there is nothing to do? playable.GetTime() seems to works in play mode only, playable.GetDuration() provides incorrect value.

I'm just printing this :
Debug.Log (inputCount+" "+playable.GetInputWeight(0)+" "+info.weight+" "+ playable.GetTime() +" "+ playable.GetDuration());

in the sample LightControlMixerBehavior, in function ProcessFrame.

If timeline is meant to make game development faster, leaner and more intuitive, then why does it pollute your project so much?

To make something so simple, you have to create so many things and jump through so many hoops. This is not just because of scriptable objects, because I extensively use Scriptable objects every day and I know their implications. This is mostly due to very bad design, especially on the naming conventions.

Please review the naming of this area of the engine in relation to the rest of the engine.

I simply dumped timeline, sorry to say, it was so far away from the needs of the everyday developer. I'm seeing it elsewhere in Unity as well. It's not a healthy direction to add so much complexity simply because the source isn't available.

I think it's a tricky task to balance usability with simplicity but I'm thinking that Unity should think more about LLAPI and HLAPI approaches, where the guts are exposed for experts and asset store developers, and the HLAPI is a simpler and much more engaging thing that is used for the other 95% of people.

Seems to me timeline was rushed out, pressured out.

TLDR: if you need a wizard, you're probably doing it wrong.

3 Likes

For clips, ProcessFrame is called every frame the clip is active. For tracks, ProcessFrame is called every frame, and it’s inputs are static. So, yes right now you need to check playable.GetInputWeight(0) > 0 for that clip to contribute.

That’s exactly the idea with the playable system. It’s a LLAPI. Unfortunately, we don’t have a corresponding HLAPI specifically tailored to timeline available yet.

2 Likes

I can sort of see your problems with it, but I think a lot of your problem is conveying that to the users so the docs and blog will help out a lot :)

I am sorry but at NO point was that ever insinuated in the videos, documentation or the big headline 2017 release landing pages.

You shouldn’t make a ton of videos touting it as easier, time saving and effortless to use when it is NOT there and wont be for at least a year.

I should mention that had timeline actually been what it was touted to be, we were ready to fork out for 2 pro subscriptions that we had been holding off on.

We have begun to trial unreal instead.

As you should, it’s necessary for any serious developer to try do feasibility studies :slight_smile:
FWIW, asset store does have timeline stuff solved by 3rd parties.