Search Unity

Since Timeline’s introduction in 2017, we know that you’ve been patiently waiting for a way to send events. Well, wait no more! Starting in Unity 2019.1, a new feature called Signals helps you send events. Let’s dive in and see what this new feature is all about.

Signals

Here’s what Signals look like in the Timeline window:

We’ve built Signals to establish a communication channel between Timeline and outside systems. But what does that mean? Why did we decide on this approach?

Let’s say that you are using Timeline to create a cutscene. When the cutscene ends, you want a new scene to be loaded and you want to enable a physics system. There are a couple of ways to implement this scenario:

  1. When your cutscene ends, use custom scripts to make your Timeline instance interact directly with a scene manager and your physics system.
  2. When your cutscene ends, create markers and signals to send a ‘’Cutscene finished’’ signal and have interested systems react to the signal.

The Timeline team went with the second approach because it keeps the emitter independent from the receiver. Keeping them independent adds a lot of flexibility, power, and reusability. To understand this more, let’s see how the different pieces work together.

How does it work together?

To use signals to communicate with outside systems, you need three pieces: a Signal Asset, a Signal Emitter, and a Signal Receiver.

  • Signal Emitter: A Signal Emitter contains a reference to a Signal Asset. In Timeline, a Signal Emitter is represented visually by a marker. You can place a marker on a track, or in the Markers area under the Timeline ruler.

  • Signal Receiver: A Signal Receiver is a component with a list of reactions. Each reaction is linked to a Signal Asset.
  • Signal Asset: A Signal Asset is the association between a Signal Emitter and a Signal Receiver. You can reuse the same Signal Asset in many Timeline instances.

Example

Here’s a simple game where you defeat a bunny zombie by pressing the arrow keys that match the directional images shown on-screen:


The directional image randomly changes with each musical beat. If you don’t press the right arrow key before the image changes, you lose. If you press a certain number of arrow keys, you win.

In the game, the GameTimeline instance includes the gameplay. It uses Signals to display new directional images with each musical beat, as shown in the finished GameTimeline instance below:

To demonstrate how to create and set up signals, let’s start from a project where none of the Signals have been created. If you want to follow along, you can download the project here.  

First, to view the Markers area where you add Signals, click the Marker icon beside the Clip Edit modes. The Markers area appears beneath the Timeline ruler:

To add a Signal Emitter, right-click in the Markers area and select Add Signal Emitter.

A Signal Emitter appears in the Markers area:

The Signal Emitter you just added is selected and the Inspector window show its properties. The Inspector window also provides buttons for creating the other pieces of a signal:

To link the Signal Emitter to a Signal Receiver, you need to add a new Signal Asset. In the Inspector window, click Create Signal…. Name the Signal Asset “ShowKey” because this Signal Asset will be used to link and emitter with a receiver to change the directional image. Click Save and the Signal Asset is added to the project.

You also want the Signal Emitter to be associated with a Signal Receiver, so click Add Signal Receiver. Your Inspector window should now look like this:

Before continuing, let’s stop and describe what’s going on. When you click the Add Signal Receiver button, two things happen: a new Signal Receiver component is added to the bound GameObject and a new reaction is added and linked to the Signal Asset that you just created. You can see they are linked because “ShowKey” appears as the Emit Signal and “ShowKey” is added to the list of reactions:

The Inspector window shows two things: the Signal Emitter properties and the reactions defined by the Signal Receiver component:

Although the Signal Receiver component is linked to the GameObject that is associated with the Timeline instance, you can edit the Signal Receiver in the Inspector window. The reaction is invoked when the Signal Receiver receives the signal.

The last step is to specify what the reaction does. In this example, there is a component named Manager with a ShowRandomKey method. This method displays a new random arrow key. To have the reaction call the ShowRandomKey method, select this method for the Unity Event, as shown below: 

And that’s it! After adding the Signal Emitter and defining its Signal Receiver and the reaction, you now have an example of a Timeline instance that communicates with the scene.

When Timeline hits the Signal Emitter, the ShowKey signal is emitted. The Signal Receiver, that is listening for the ShowKey signal, calls the ShowRandomKey method.

But you don’t have to stop there. Multiple signal emitters can emit the same signal. For example, the following Timeline instance has the same Signal Emitter copied and moved to different times; there is an emitter for every musical beat:

You can also drag a Signal Asset directly from the Project window to the Timeline window. A Signal Emitter is automatically created with the Emit Signal property already set.

To see what the finished project looks like, with all Signals, download it here.

To summarize

In order to set up your first signal, you need to:

  1. Right-click on a Marker area or a track that supports signals, then choose Add Signal Emitter…
  2. In the Inspector window, click Create Signal Asset, choose a file name and press Enter.
  3. Still in the Inspector, click Create Reaction… button and define the reaction associated with the signal you just created.

Bonus FAQ

  • Can I have multiple receivers on a single GameObject? Yes, all Signal Receivers on a GameObject receives the signals sent to that GameObject.
  • Can a signal asset be reused between multiple Timeline instances? Yes, a Signal Asset can be used in more than one Timeline instance.
  • Can a Signal Asset be extended and customized? Yes, Signal Asset, Signal Emitter and Signal Receiver can all be extended. But this is a subject for another day; there will be another blog post about customization.
  • Are signals guaranteed to be emitted? Yes. Signals will not be skipped; they will be emitted on the next frame regardless of the game’s FPS.
  • What happens if duplicate a Timeline Asset contains signal emitters? The signal emitters keep their reference to their Signal Assets. Signal Assets are not duplicated.

 

Check out beginner and advanced learning content for using Timeline on the Unity Learn Premium platform.

21 评论

订阅评论

评论被关闭。

  1. Can markers and signal emitter properties be accessed/modified via script? For example, can you change the position of a marker on a timeline during runtime? Create a new marker and assign a Signal asset on a Timeline during runtime?

    My apologies if I missed an obvious answer to this somewhere! Thanks!

    1. Yes, signal emitter properties can be accessed and modified in a script. You can also change the position of a marker or create a new one and assign a signal at runtime .

  2. I’m just going to go on a limb here and say that not only does this feel over complicated..

    But the “demo” that was shown as an example I think doesn’t quite show it’s full capability. How many here are actually using this to build a Rhythm Game?….

    Maybe having a demo that switches between animation states for a character based or a system that effects the lighting of an environment (all based off a signal) might be a better example for curious developers…

    Going into this as one of those curious developers – I can tell you that after reading this and seeing the provided demo. I’m not interested or intrigued…

    I mean no ill will – just trying to provide useful and critical feedback to hopefully improve the engine I love! :)

    1. Thanks for your feedback!
      I understand when you say that signals can feel over complicated. At first, it can feel like so. I think that by using signals you will discover why we chose that design. If not, feel free to comment here or on the forums.

      About the demo: Whilst not everybody wants to make a rhythm game, I tried to show a simple example; I wanted to focus solely on signals. I thought it could be a good way to showcase signals in a visual way. Next time I will try to integrate more details for curious developers.

  3. I think you forgot a very important case in your Bonus FAQ:
    How are Signals handled if one is manually controlling timeline time? Cases: a) jumping in timeline
    b) syncing timeline from an external source (e.g. “usually going to the next frame but not quite always”)
    c) scrubbing timeline backwards

    1. Signals are not send while scrubbing (ie calling Evaluate() on a PlayableDirector), so jumping in a timeline or scrubbing backwards will not emit signals.
      However, signal emitters have a Retroactive property, which will emit the signal if the timeline begins playing after the signal. Let’s say you have a signal at time 1 with Retroactive toggled on. If you start playing the timeline at time 2, the signal will be emitted right when the timeline starts playing. This is useful for signals that trigger a LoadScene(), for example.

  4. I’m going to join the others commenting here in expressing that this seems both unnecessarily complicated, and also limited in expected functionality as opposed to an event system where any game object could listen for an event broadcast by a timeline.

    Is the awkward implementation of this going to have some pay-off with DOTS (ECS) that we’re not seeing?

    1. We chose that design because it makes for a very clear list of dependencies between Timeline and a scene.
      To emit signals on multiple objects at once, you can setup a reaction that will call all the appropriate methods on each GameObjects you want.

      Also, we are still working on how timeline will work in DOTS, so I can’t comment about that right now.

  5. Carl Emil Carlsen

    五月 22, 2019 11:53 上午

    I am not sure I understand the design decision of inventing additional assets and concepts for this problem. It seems over complicated. I imagine the decision will potentially result in a confusing ocean of signal assets. I also find it illogical to select a marker that I want to emit/transmit/send from, and then being shown a “SignalReceiver” containing a UnityEvent in the inspector. Why not just add a UnityEvent directly to a marker?

    1. A marker being an asset, this created problems with UnityEvents, since those need to reference objects in the scene. We also want timelines to be reusable, and having UnityEvents embedded directly in a marker prevented timelines to be reused in multiple scenes.

  6. Im also confused as to why we have to attach to the receiver? Why on have a kind of awake() function execution when the marker is hit and allow the user to add any component to the signal. That way it more of a gameObject activating at a certain time, then we can also script into that marker anything we want. Or maybe I didn’t understand the post.

    1. A Timeline can emit signals to Gameobjects with the following rules:
      – If the signal emitter is on the timeline itself (under the time area), the Gameobject that has the PlayableDirector component used to play the timeline will receive the signals.
      – If the signal emitter is on a track, the Gameobject bound to the track will receive the signals.
      A SignalReceiver component placed on a GameObject will be able to respond to signals. You can then setup what the receiver will do when it receives a signal.

      1. Got it , thanks for clarifying

  7. There is one think I do not understand, the receiver is on the bound object, why ? What if I want many objects to be notified ? I thought a receiver could reference a Signal asset and subscribe to an event which would have been trigger when the Emitter is reached in the Timeline.

    1. Matthew Holtzem

      五月 21, 2019 6:13 下午

      Yeah I second this. you say “The Timeline team went with the second approach because it keeps the emitter independent from the receiver.” but at the end of the day if everything has to be pre-determined and bound together by the timeline it doesn’t really seem like they are independent. If I can’t spawn in a prefab with a signal receiver on it at runtime then I don’t really see what you gain by this asset based approach aside from making it more complicated

      1. A signal is just a scriptable object they are using to pass events – such as described by Ryan Hipple (https://unity3d.com/how-to/architect-with-scriptable-objects).
        A signal receiver is just a component with a reference to a signal; You can spawn in as many prefabs as you want they just need a signal receiver component with a reference to the signal and they will receive the event from the timeline… it’s pretty easy

        1. Matthew Holtzem

          五月 21, 2019 7:45 下午

          That’s how you would think it would work but it doesn’t actually behave that way. In order for a gameObject to receive a signal emitted from the signal emitter it needs to be bound to the timeline. So even though the receiver has a reference to the asset, and the emitter has a reference to the asset, they still need to be connected by a timeline track :(

        2. From what they said in the blog post and in the forum the receiver has to be bound to the timeline so it’s quite different from Ryan Hipple approach which is much more flexible.

    2. Signal emitters will only send signals to objects bound on their parent track (or on the Gameobject that contains the PlayableDirector component, if the emitter is on the marker area).
      We chose that design because it makes for a very clear list of dependencies between Timeline and the scene.
      To emit signals on multiple objects at once, you can setup a reaction that will call all the appropriate methods on each GameObjects you want. A SignalReceiver can invoke methods on any GameObjects in the scene.

      1. It is what it is. But it is not really a convenient and intuitive way to have receiver bounds to the timeline. Regarding the blog post example I could want characters, NPCs, props or whatever (already in scene or dynamically instantiated) be in sync with the timeline audio beats. Be able to simple add a Receiver on those objects to achieve that would have been far easier that put one receiver on the timeline ruler, received the Signal and then re-dispatch the event to all those objets.

  8. This is awesome stuff, been waiting for this since sometime in 2017 and its finally with us! And it looks as good and as useful as hoped!