This track can be used for simple transform movements between two points.
This track can be used for simple transform movements. All translation happens in a straight line but the speed can be controlled with an animation curve. The Tween track binds to the scene Transform you wish to move.
| Field | Description |
|---|---|
| Start Location | This is a reference to a Transform in the scene that marks the position and/or rotation of the moving Transform when the playable starts. If it is left null the position/rotation of the moving Transform when the playable starts will be used. |
| End Location | This is a reference to a Transform in the scene that marks the position and/or rotation of the moving Transform when the playable finishes. |
| Tween Position | Whether or not the position of the Transform should change. |
| Tween Rotation | Whether or not the rotation of the Transform should change. |
This example will demonstrate how to:
ClipEditor;when a Timeline begins playing, nodes called Playables are created. They are organized in a tree-like structure called the PlayableGraph. For each frame, Timeline samples this graph to read and mix multiple data sources (animation, audio and more).
The first step to create a custom clip is to define a new PlayableBehaviour that will be added to a graph. It will need to store the data needed to implement the transform tween:
public class TweenBehaviour : PlayableBehaviour
{
public Transform startLocation;
public Transform endLocation;
public bool shouldTweenPosition;
public bool shouldTweenRotation;
public AnimationCurve curve;
}
The PlayableBehaviour's data is not serialized and will be lost once its parent graph is destroyed. To save this data, the next step is to define a new PlayableAsset:
[Serializable]
public class TweenClip : PlayableAsset
{
public ExposedReference<Transform> startLocation;
public ExposedReference<Transform> endLocation;
public bool shouldTweenPosition = true;
public bool shouldTweenRotation = true;
public AnimationCurve curve;
//...
}
Note: The clip needs to store a start and an end location. Since an asset cannot directly reference a scene object, it cannot store a transform object directly. This is why an ExposedReference<Transform> is used.
A PlayableAsset's main purpose is to build a PlayableBehaviour. This is done with the CreatePlayable method:
public class TweenClip : PlayableAsset
{
//...
public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
{
// create a new TweenBehaviour
ScriptPlayable<TweenBehaviour> playable = ScriptPlayable<TweenBehaviour>.Create(graph);
TweenBehaviour tween = playable.GetBehaviour();
// set the behaviour's data
tween.startLocation = startLocation.Resolve(graph.GetResolver());
tween.endLocation = endLocation.Resolve(graph.GetResolver());
tween.curve = curve;
tween.shouldTweenPosition = shouldTweenPosition;
tween.shouldTweenRotation = shouldTweenRotation;
return playable;
}
}
CreatePlayable will initialize a new TweenBehaviour using TweenClip's data.
A custom track is created by defining a TrackAsset subclass. The following attributes can be added to a TrackAsset:
For this example, the track needs a Transform object binding and can only accepts clips of type TweenClip, which was previously defined in step 1:
[TrackBindingType(typeof(Transform))]
[TrackClipType(typeof(TweenClip))]
public class TweenTrack : TrackAsset
{
// ...
}
The data setup is complete; TweenTrack and TweenClip can now be added to a timeline:
However, no transform tween has been implemented yet. To do this, a track mixer is needed.
To properly handle blending, or crossfading, between two clips, a track mixer is needed. A track mixer is a PlayableBehaviour that will have access to all clips data and will blend those together.
By default, when a track is added to a timeline, an empty playable is generated and is connected to each clip's playable.
For example, this track:
will generate the following playable graph:
Timeline: this playable is the root playable; all playables related to tracks are connected to this node.Playable: this playable represents the track mixer. Since no track mixer is defined, an empty one is generated.TweenBehaviour: this playable represents a clip. One per clip is generated. All clip playables are connected to the track mixer.In order to define a custom track mixer, a new PlayableBehaviour needs to be defined:
public class TweenMixerBehaviour : PlayableBehaviour {}
then, in TrackAsset, the CreateTrackMixer method can be used to specify a custom track mixer:
public class TweenTrack : TrackAsset
{
public override Playable CreateTrackMixer(PlayableGraph graph, GameObject go, int inputCount)
{
return ScriptPlayable<TweenMixerBehaviour>.Create(graph, inputCount);
}
}
Now the playable graph looks like this:
The empty playable that used to connect clip playables together is now replaced by TweenMixerBehaviour.
The implementation of the transform tween resides in the ProcessFrame method from TweenMixerBehaviour. Here are the main steps of that implementation:
null, the initial transform will be used instead.// Iterate on all the playable's (mixer) inputs (ie each clip on the track)
int inputCount = playable.GetInputCount();
for (int i = 0; i < inputCount; i++)
{
// get the input connected to the mixer
Playable input = playable.GetInput(i);
// get the weight of the connection
float inputWeight = playable.GetInputWeight(i);
// get the clip's behaviour
TweenBehaviour tweenInput = GetTweenBehaviour(input);
}
// Apply the final position and rotation values in the track binding
trackBinding.position = accumPosition + m_InitialPosition * (1.0f - totalPositionWeight);
trackBinding.rotation = accumRotation.Blend(m_InitialRotation, 1.0f - totalRotationWeight);
ClipEditor can be used to augment the capabilities of a clip in the editor. It works like a custom Inspector; the CustomTimelineEditor attribute is used to tell Timeline that a ClipEditor class should be associated to a given clip.
[CustomTimelineEditor(typeof(TweenClip))]
public class TweenClipEditor : ClipEditor
{
//...
}
It is possible to customize the appearance of a clip with the DrawBackground method:
public override void DrawBackground(TimelineClip clip, ClipBackgroundRegion region)
{
TweenClip asset = clip.asset as TweenClip;
if (asset == null)
return;
// Drawing code here...
}