I’ve created a custom track to hold all the actions my characters will perform in timeline. I’ve made all these actions inherit from an absctract class called CharacterPlayable which itself inherits from ScriptPlayable
I’d like to be able to add only these actions in my CharacterTrack, but I can’t find a way to do this.
Here are some snippets of my code :
[TrackBindingType(typeof(Character))]
[TrackClipType(typeof(CharacterPlayableAsset))] //Also tried with CharacterPlayable
public class CharacterTrack : PlayableTrack {
}
[System.Serializable]
public class LookAt : CharacterPlayableAsset {
public ExposedReference<GameObject> Agent;
public ExposedReference<Transform> Target;
public override PlayableHandle CreatePlayable (PlayableGraph graph, GameObject owner)
{
var handle = graph.CreateScriptPlayable<LookAtPlayable> ();
handle.GetObject<LookAtPlayable> ()._agent = Agent.Resolve (graph.resolver);
handle.GetObject<LookAtPlayable> ()._target = Target.Resolve (graph.resolver);
return handle;
}
}
[System.Serializable]
public class LookAtPlayable : CharacterPlayable {
public Transform _target;
public GameObject _agent;
public override void ProcessFrame (FrameData info, object playerData)
{
_agent.transform.LookAt (_target);
}
}
I also have an other class build on the same method as LookAt that also inherits from CharacterPlayableAsset.
When I right clic on my CharacterTrack in Timeline, I expect to see both methods I’ve created, but I only get the option to add a CharacterPlayableAsset (which is abstract), and I get the following error when I do so :
I have also tried to add one “TrackClipType” per class I want to be able to select, but it only keeps the last one.
I’m starting to think this is a bug … the documentation uses plural for “Scriptplayables” and “clips”, which leads one to assume you should be able to add multiple trackcliptypes using this. If this is a bug, can we get a confirmation on this, so we can leave it as is in the code for now and assumably have it fixed in a coming update?
From the docs: "Specifies the type of PlayableAsset or ScriptPlayables that this track can create clips representing.
This is required for custom track assets to specify the type of clips to create."
Having similar problems. I’m trying to add multiple Clip types to the same Track in very much the same idea.
I don’t think it’s a bug - neither Editor-internal Timeline Tracks nor the DefaultPlayable Track examples show a single Track that would have this kind of behaviour that it would take multiple Clip types (Animation and Audio tracks have multiple context click menuitems, but they are only shortcuts to select a different source for the setup of single-type the Audio/Animation type Playables for their respective tracks).
For now I’m planning to make some kind of Clip class to hold all kinds of parameters and then inheriting that class just to have different PropertyDrawers that expose only desired fields to the Inspector - I’d much rather just inherit the base class used as the TrackClipType and setup the parameters neatly per child class, but I suspect Unity’s serialization would lose sight of the data stored in child class type if the Clip stores a serialized field that is the type of the base class.
Should it be possible to use an interface for the TrackBindingType attribute as with TrackClipType above? In 2019.2.19f1 the track binding disappears when specifying an interface, so I’m forced to create an additional concrete class to act as a binding.
Good question. I don’t believe it is possible at the moment, as the requirement is the binding should be a Unity Object so that a reference to it can be serialized.
But, should it, is a completely different story. I’d say it probably should, provided it’s a Unity Object that implements that interface, and just an oversight on the use case on our part.
It feels like it would be in keeping with the usage of TrackClipType, as they’re often used side-by-side when creating a custom track. In fact I usually implement an interface anyway that I use when I access the track binding inside the playable behaviours and when I call out to my own logic. The Unity Object is only there as a go-between but it’s always nice to eliminate unnecessary code!
Using a base class that derives from PlayableAsset is really the only way currently.
You could also use ClipEditors (or TrackEditors) to display errors when the clip doesn’t implement a particular interface as well. For example, have all your custom clips inherit from an abstract PlayableAsset-derived class, and have your custom track show errors when the clip type does inherit from an interface.
Far from an ideal solution, as the user really shouldn’t be able to add invalid clip types, but maybe there is something in there that helps your use case.