Plugin to bind objects to a PlayableAsset
used on Timelines and load your Timeline in runtime.
By default, a PlayableAsset
can hold references to elements that coexist in the same scope as them.
Let's suppose that we have a Timeline
that has a reference to the Main Camera of the scene. If this Timeline
exists on the scene the reference will be there and the timeline will be able to manipulate the referenced camera.
Now, if we move the Timeline
to a prefab that will be loaded at runtime, the Main Camera reference will be lost. To solve this issue we would have to bind the element by code.
This plugin helps with the process of binding elements in runtime.
To make it work, we have to create our Timeline
and assign the references on Edit mode, then we will use the plugin to wire the objects that are referenced on it.
And we should be ready to go.
1.- Work on a Timeline and add object references to it, as usual. So a timeline like this:
Also, you can see on Unity Inspector the current bindings:
2.- Add a PlayableDirectorBinder
component and assign the PlaybleDirector
component to it on the Director
field.
3.- Wire the elements using the button that says Wire bindings!
on the PlayableDirectorBinder
component.
This will do two things;
- First, Add a
BindableAsset
component to each of the referenced objects. This new component will hold a unique identifier and a reference to the bound object. - Second, update the names of each one of the
tracks
on theTimeline
to include that unique identifier (later this name will be parsed to look for the object with that unique Id).
Updated track names:
New BindableAsset
component:
4.- Save your changes and load your Timeline in runtime. By default, PlayableDirectorBinder
will try to bind elements on Awake
but this option can be disabled (this would require a manual invocation of SearchAndBindObjectsOnScene()
on PlayableDirectorBinder
).
There are other buttons on the PlayableDirectorBinder
component besides Wire bindings!. Those are useful for testing or cleaning up things:
- Wire bindings!: Add a
BindableAsset
component to referenced objects and update the track name accordingly. If there is already aBindableAsset
component on the referenced object, it will just update the track name. In the case that the unique Id on theBindableAsset
doesn't match the specified Id on the track name, the track name will be updated. - Search and bind scene objects: Search on the current scene and try to bind elements using the unique Id specified on the track name.
- Cleanup binding references: Unbind all the references. Useful if, after Wire the bindings you want to see if everything is working. (ie; First Wire... the bindings, then Cleanup..., then Search and bind.... If you are in the scene where the timeline will be loaded, all the references should be re-bound).
- Reset track names with assigned components: Reset the name on all the tracks that have an assigned component. So you always can wire and the track names should go back to their previous values.
- Reset *ALL* track names: Rest the name on all tracks, without filtering those that have or have no references. If you reset the name of a track that has nothing assigned to it, it will be on you to reassign a valid reference.
- The process to obtain the
BindableAsset
references relies on Finding Objects Of Type All that exist on a loaded scene (Resources.FindObjectsOfTypeAll<BindableAsset>().Where(ba => ba.gameObject.scene.isLoaded);
). This can cause issues with thePlayableDirectorBinder
optionTry Bind on Awake
if thePlayableDirectorBinder
is being instantiated at the same time. In other words, the current way to look upBindableAsset
cannot retrieve them duringAwake
if they are also being instantiated. So make sure that you have the requiredBindableAsset
elements already loaded before loading aPlayableDirectorBinder
. A workaround for this is to manually invoke theSearchAndBindObjectsOnScene()
method after the scene is loaded with both elements.
- Improve the lookup function;
FindObjectsOfTypeAll
can be expensive. - Improve assignment function: Currently, after retrieving all the
BindableAsset
we try to bind each one of them. A better solution would be to a dictionary.