New in 2019.1 - Marker Customization

A new item has appeared: markers!

A marker is new item that can be added to a timeline. It is used to represent a point in time.
Markers can be added and manipulated on a timeline the same way as clips; selection, copy-paste, edit modes etc. should work. A markers also has a specialization, just like clips (Animation Clip, Activation Clip, Control Clip, etc.). In 2019.1, Timeline offers its first built-in marker: Signal Emitter marker. See this thread to know more about signals.

It is also possible to write custom markers!

How to create a custom marker

In order to let timeline know that you have a new type of marker, all you have to do is to create a class that inherits Marker.

public class CustomMarker : UnityEngine.Timeline.Marker {}

That’s it! This custom marker can now be added on any track and on the timeline marker area.

At this point, the custom marker is only a visual item on the timeline. This means that this marker cannot invoke code when triggered. That doesn’t mean it is not useful; a marker can be a snap point or a chapter. It is also accessible through the Timeline API in editor and at runtime

How to create a custom marker that will invoke code

In order to have a marker trigger something, it needs to implement the INotification interface.

{
public PropertyName id { get { return new PropertyName(); } }
}```

Implementing the *INotification* interface will tell timeline that the marker will need to react when triggered.

The *INotification* interface is part of the *Playable* notification system. Each marker that implements *INotification* will have a node added in the timeline’s *Playable Graph*.

![](https://lh3.googleusercontent.com/5fiCwrwEHB0MUl_SMhqklZc0f25HqJiwqhRlswqZDvUXsrSMIr6v0HvBSGtueWEGpFvDFWWTIn1HutS95mlaa3832CfmOj_41rzpFr1ezTZiMVa5K1m-nOSZbGoKTrIhfKngsQ36)

To make things clear, here’s a table of the particularities of the different ways to create custom marker:
![3973417--341242--upload_2018-12-7_17-13-27.png|559x172](upload://wwNPdGGEd5NouTzR21w9lcjIQAy.png)

When a *INotification* node in the *Playable Graph* is sent, the *PlayableOutput* will receive it. One last piece will need to be added in order to process this notification.

```public class MessageReceiver : MonoBehaviour, INotificationReceiver
{
public void OnNotify(Playable origin, INotification notification, object context) {}
}```

The *PlayableOutput* will need to have a *CustomReceiver* component in order to receive and process the *INotification*s.

Here’s a summary of what you need to do if you want to invoke code with your custom marker:

- Create a class inheriting from Marker and implementing *INotification*.
- Create a component implementing *INotificationReceiver*.
- Add this component on the correct Gameobject

- If your custom marker is on a track, add the component on the track’s bound object.
- If your custom marker is on the timeline itself (the timeline marker area), add the component on the Gameobject that has the *PlayableDirector* component.

In order to show you what is possible to do with custom markers, I created Message markers. These markers act like Animation events, but directly in the Timeline. **See this [Github repo](https://github.com/Unity-Technologies/Timeline-MessageMarker) to download the project and see how I did it.** The relevant[ code is here](https://github.com/Unity-Technologies/Timeline-MessageMarker/tree/master/Assets/MessageMarker) (the rest is just inspector code).

**One last thing...**

We just saw that we can customize the behaviour of a marker. But that is not the only you can do; it is also possible to customize a marker’s appearance. It is not yet available in 2019.a11, but it will release in 2019.1. Stay tuned.
11 Likes

Is there a particular reason as to why this example uses custom code to extract available methods from the gameobject in question instead of using a regular UnityEvent? Is it only to show that you can directly reference the bound object?

Ok, I get it, UnityEvents don’t have a way to insert context in them, so if they’re in an asset (like something from a Timeline, which obligatorily resides in an asset), they can only see Assets.

UnityEvents really should get a little power-up. They can only have a single parameter, you need to inherit from them because Unity can’t serialize generic stuff, and now this as well.

4 Likes

From my perspective:

The sample is more demonstrating you can build the old (and kinda not great, what with the SendMessage call and fixed argument types) animation events functionality on Timeline if you really wanted to. This could be useful if you’re moving from a cutscene controlled by an Animation clip to a cutscene controlled by a timeline and you wanted to salvage code that relied on the old events system before fully migrating to a cleaner setup with signals or other custom marker types specific to your use case (and likely more performant that this by a good margin).

UnityEvents are just a way to serialize parameters and delegate references to other objects in the editor, they’re not a great solution for completely decoupled communication due to way delegates work. The subscriber has to know about where the UnityEvent’s containing object is before subscribing/unsubscribing. On top of this, Delegate invocation is often the slowest type of call in the .NET framework and UnityEvents add another layer on top of that.

The signals way is just a contract using the Signal Asset as a token that maps to a function call. This allows a more complete decoupling. That said I’ll need to get on the 2019.1 alpha at some point and actually get a feel for it before I go deeper into the pros and cons.

I can see where your frustration lies, the signals way is very different than what seems to be intuitive but there may be performance/implementation simplicity reasons for going that route that remain unseen what with all of this being brand new.

Sure, that looks pretty much like the idea, even if only to serve as an example:

Nothing much to add to that, it was more that I didn’t really understand the reason as to why not use UnityEvents in a case in which they’d have been able to fulfill exactly the same purpose. That is, until I realised why.

That could easily be solved, I think, by extending the UnityEvent API to allow for it to have basically that same UI, but also to have context injected into it. In this case, it could even use the kind of references the Timeline Asset itself uses, with Exposed Properties which are populated through the Director Component.

I haven’t read the UnityEvent source code yet, and by a glance it does seem to be quite intricate, but it surely is far from being one of Unity’s most complex features. Given it’s importance, I do think it’s worth the investment into improving it.

See, that I don’t buy as a problem. At all. At which order of magnitude in call counts would you have to be for your timeline events to actually become a performance problem? You’d need to have an insane amount of events at the same frame, which makes no sense at all if you think about most if not any use case for Timeline. And, of course, you could write your own call system if you are in one of the unlikely edge cases.

Yes, I realize that as well. I even mentioned it in the other thread. Although I do lack to see the reason as to why that much decoupling would be necessary. As I mentioned in the other thread, the current way the system does it is by creating an insane list of signals with only their names to help identify them. I think it’d be much better if they could lie in Timeline Assets themselves, at least. That way, at least you’d have the context in which said signal name is supposed to happen.

The problem with this approach is it forces all of the context to the callee, leaving none of it to the caller. In some cases, it’d be very useful to be able to divide it between the two, as my example with “A bunch of slighly different explosions” tries to illustrate.

My frustrations don’t lie simply on the Signal system itself (although I’ve already explained a bit of the problems I immediatly see in it in the other thread). It’s more on the fact that said complexity could be opt-in. There are a ton of usecases in which said complexity isn’t needed at all, as a lot of sequences can be directly mapped to the scene they should reside in.

Something else I always forget to say:

There is no visual cue for a selected marker in the Timeline view. Is it just a bug for me or was this never present? Shouldn’t it be blue when selected, like every other selectable piece of the UI?

@julienb could you quickly explain what a Marker Track does? It seems to be related, talking about Markers and all, but it’s never mentioned, explained anywhere, used…

A marker should be white when selected. 4072336--354898--upload_2019-1-7_11-42-5.png

Marker Track is a utility class that you can inherit from when creating custom tracks. It is a track that does not accept clips.

By the way, the Marker Track should never have been shown in the Add menu:(. It’s a bug that appeared right before releasing the alpha version.

Hihi, I thought something like that was the cause.

Thanks for this awesome API!

I have a question: when you select “Loop” for the timeline’s “Wrap Mode” all my custom markers are fired simultaneously right at the beginning of the next round of the timeline. Why is that?

Also, it would be cool, to be able to specify the type of marker a receiver can process.

Something like:

public class MessageReceiver : MonoBehaviour, INotificationReceiver<Message>
{
    public void OnNotify(Playable origin, Message message, object context)
    {
        var methodToCall = message.method;
        var argument = ArgumentForMessage(message, origin.GetGraph().GetResolver());
      
        if (EditorApplication.isPlaying)
            SendMessage(methodToCall, argument);
    }
}

Or maybe with a class-attribute like

[MarkerType(typeof(Message))]
public class MessageReceiver : MonoBehaviour, INotificationReceiver
{
    public void OnNotify(Playable origin, INotification notification, object context)
    {
        var message = notification as Message;
        var methodToCall = message.method;
        var argument = ArgumentForMessage(message, origin.GetGraph().GetResolver());
      
        if (EditorApplication.isPlaying)
            SendMessage(methodToCall, argument);
    }
}

Seems weird… Do you have the Retroactive flag enabled on your markers?

I think it’s a good suggestion! Right now you’ll have to filter the markers manually.

It works when I implement the INotificationOptionProvider and return the default NotificationFlags:

public NotificationFlags flags => default;

I assumed that Unity uses the default flags by default when I don’t realize INotificationOptionProvider at all…
Is this a bug or desired behaviour?

By default, a notification will have NotificationFlags set to retroactive. (API doc).

However,

that is a bug. I just verified and you are right, when the timeline is looping and retroactive is true, notifications are fired when they shouldn’t be. Thanks, I’ll fix ASAP.

I have a question regarding implementation of signals. I have a script on an object with a function that takes a boolean. I would like to be able to set that bool with the signal to true or false. Does this mean that I’d need a signal for true and another for false?

This becomes less useful for cases where I need to pass a string. How would one go about implementing that case, if possible, using a signal and not needing a new signal for every possible string variation?

Hi, small question. Is this already available? Or is it “Timeline: Added ClipEditor, TrackEditor, and MarkerEditor classes the user can derived from to modify custom clips, tracks and marker functionality inside the Timeline Editor” in the 2019.2 patch note? If not available, will it be backported during 2019.1?

ClipEditor, MarkerEditor and TrackEditor are available in 2019.2 only. They won’t be backported to 2019.1, unfortunately.

1 Like

Thank you, one more question. In 2019.1 I saw an attribute [UnityEngine.Timeline.CustomStyle(“ussStyle”)] available. It looks like what could do a subset of what MarkerEditor can. So for the time being I want to style the marker based on this while waiting for 2019.2. Is there any documentation on this?

So in the code I saw [CustomStyle(“SignalEmitter”)] and I could also apply that style over my custom marker, and the default (curved top) custom marker style changes to be like the signal emitter (flat top). This is an image before CustomStyle, when applied with [CustomStyle(“SignalEmitter”)], they are indistinguishable.

4484758--412831--Screenshot 2019-04-30 15.46.50.png

So when I create multiple custom markers I want to be able to discern them at glance rather than them being all curved top. I tried [CustomStyle(“MyStyle”)] according to the code comment :

    ///<summary>
    /// Use this attribute to customize the appearance of a Marker.
    /// </summary>
    /// Specify the style to use to draw a Marker.
    /// <example>
    /// [CustomStyle("MyStyle")]
    /// public class MyMarker : UnityEngine.Timeline.Marker {}
    /// </example>
    /// Then, add a 'common.uss' file in the Editor folder.
    /// Create an element to customizes the appearance of the marker.
    /// <example>
    /// MyStyle
    /// {
    ///   /* Specify the appearance of the marker in the collapsed state here. */
    /// }
    ///
    /// MyStyle:checked
    /// {
    ///   /* Specify the appearance of the marker in the expanded state here. */
    /// }
    ///
    /// MyStyle:focused:checked
    /// {
    ///   /* Specify the appearance of the marker in the selected state here. */
    /// }
    /// </example>

I have already add “common.uss” to the Editor folder with empty styles like the documentation, but I get this warning “Cannot find style MyStyle for MyMarker”. I even tried changing “MyStyle” to “MyMarker” (In the same fashion that Unity is doing “SignalEmitter” style for “SignalEmitter”) but it still throws a warning “Cannot find style MyMarker for MyMarker”. What am I missing to make this work in 2019.1?

Maybe you could make a custom SignalReceiver with a pair of SignalAsset → UnityEvent<bool/string> instead? Then make a custom SignalEmitter that also holding bool/string. Then, in your custom receiver’s OnNotify after matching the correct SignalAsset, you could invoke the event with parameter from the emitter. This way you could still use the UnityEvent dropdown to select your method with bool/string argument (without specifying a parameter, it is now dynamic)

4484944--412906--Screenshot 2019-04-30 16.44.21.png

The editor for SignalAsset → method pair didn’t look as good as SignalReceiver however, but it is workable. In this example when the timeline passed through my marker with true, the audio source will be looped.

4484944--412909--Screenshot 2019-04-30 16.42.17.png