UnityEvent, where have you been all my life?

I just stumbled upon UnityEvent thanks to another thread. I went looking to help someone, but ended up being helped myself, in a big way. In case there’s anybody else out there still wandering in a cloud of ignorance, as I was, I thought I’d try to bring it some more attention.

I may have overlooked it before because the docs (here and here) are rather spartan, not quite up to Unity’s usual clear tech-writing standards. But a little experimentation shows they’re really easy to use. Say you have a script that occasionally flips a sprite, and you think this flipping is something other scripts might want to know about. Just use UnityEngine.Events at the top of the file, declare a public UnityEvent property, and then call .Invoke() on that property at the appropriate time, like so:

using UnityEngine;
using UnityEngine.Events;

public class FlipTest : MonoBehaviour {

    public UnityEvent flipped;

    void Update() {
        if (Input.GetKeyDown(KeyCode.Space)) Flip();
    }

    void Flip() {
        transform.localScale = new Vector3(-transform.localScale.x, 1, 1);
        flipped.Invoke();
    }
}

Now, check out the inspector for this component in your scene:

Initially that “Flipped ()” list is empty, but I’ve already smacked the + button twice to hook up two receivers. And, right in the UI, it’s pretty amazing — you can invoke almost any method or set any public property (!) of any component of any object in the scene. For example, the first one above changes the name (Behaviour.name) of the main camera to “Foo!”. No code required — as soon as this sprite flips, the main camera’s name gets changed!

The second one above is slightly more practical; I had a script called EventLogger, with a method like this:

    public void Log(string msg) {
        Debug.Log(gameObject.name + ": " + msg);
    }

As you can see in the inspector screenshot above, it was trivial to not only invoke this method, but specify an argument. So now when the sprite flips, the camera gets renamed and the “It works! Holy crap!” message appears in the Console.

This is an extremely powerful system for decoupling your classes and components. The sender of the events doesn’t have to know anything about the receivers (at least, at the code level). The receivers don’t have to know anything about the senders. It doesn’t depend on matching things up by name, it doesn’t search the hierarchy. In the past I’ve rolled my own notification systems to accomplish things like this, but now that I know about UnityEvent, it may not be needed.

If there’s anything to not like about UnityEvent, it may be that it’s too powerful. It allows the scene editor (who is often a designer, rather than a programmer) to do all sorts of foolish things, like renaming the main camera, which could well break a project. There’s certainly enough rope here to shoot yourself in the foot. But I doubt it would often be a problem in pratice. And of course regular old strongly-typed properties are still an option for when hands need to be more tied.

I’ve always felt that intercomponent communication was a weakness of Unity’s framework design — SendMessage and Broadcast are evil, and using specific-typed properties leads to strong coupling. This is the missing piece that makes the component approach really work, and it deserves more than one cryptic page in the manual and a slim section of the scripting reference. Everybody should be using this, in a large portion of their scripts.

If this was useful to you, let me know with the poll above… if it’s caused a light bulb to go off for even one other person, I’ll know my time wasn’t wasted!

Cheers,

  • Joe
62 Likes

I’ve been wanting a Unity-driven event system for yonks. I use delegates myself but have been meaning to check out Unity’s new system, and will do so with whatever project I start next.

I’d need a “I knew about them and they sound neat, but I haven’t checked them out yet.” option. :wink:

3 Likes

For the sake of people who don’t understand the benefit, amongst other things events:

  1. are a way to allow your objects to communicate with one another without being aware of one another, and
  2. allow you to run code in response to changes, instead of code that checks for changes.
15 Likes

I only got into this since January. I love them. It’s partly from my background with Flash and AS3, where I used events a lot, and it felt like a step backward when I didn’t have a comparable thing in Unity.

One thing you left out that I love is AddListener()

My reason is sometimes it’s nice to approach it from the opposite direction like this. An object can invoke an event without needing to know which objects are listening for it.

For an example I had a game set to music, where I wanted certain things to happen on the beat. So I had a BeatCounter class with a static variable beatEvent and the BeatCounter invoked it according to the timing of the song. And so anything else in the game that I wanted to move to the beat would use BeatCounter.beatEvent.addListener(functionName) to perform an action on the beat.

11 Likes

UnityEvent <3<3<3<3<3

I’m writing a cutscene system, and I were creating special wrapper classes for different actions - one for moving a character, one for fading the screen, and so on.

I realized that each cutscene had me writing at least one special action that would be used just there, and I thought that I should try to make a general system. So I went digging through the UI source to figure out how buttons did their magic, and found the UnityEvent. Holy cow it’s powerfull.

I was kinda considering making this thread myself. Like, the power of just putting this little class here on different gameobjects:

public class UnityEventWrapper : MonoBehaviour {

    public UnityEvent unityEvent;

    public void Invoke() {
        unityEvent.Invoke();
    }
}

Somewhat crazy. I love it! The docs are way too sparse, and this should probably have a tutorial somewhere. It’s probably just the engineers at Unity that made this thing and kinda forgot that it was super-awesome at one point along the way.

5 Likes

What you are doing here was possible before UnityEvent using a even cleaner syntax. Since C# already has events and delegates out of the box. Which works great when it is all done in code very easy to have a class subscribe to a static event.

What makes UnityEvent great is it provides a way to do this in the inspector on a per object level instead of doing it in the class.

3 Likes

[quote=“passerbycmc, post:6, topic: 577808, username:passerbycmc”]
What you are doing here was possible before UnityEvent using a even cleaner syntax. Since C# already has events and delegates out of the box. Which works great when it is all done in code very easy to have a class subscribe to a static event.
[/quote]Vanilla C# events/delegates cannot be saved into scenes/prefabs, though. So even if you wrote an editor extension to let people plug things into them in the Inspector, you wouldn’t be able to use them to actually build up persistent stuff.

6 Likes

Aside from what has been mentioned above, another benefit of UnityEvents over C# events and delegates is that they maintain only a weak reference to the subscribers and handle Unity object destruction properly.

Hence, if a runtime-added listener is destroyed without unregistering with the event, it will still get properly garbage collected and will not receive invokes in a bad state.

Also, I came across this omission in the API the other day - toss some votes :slight_smile: http://feedback.unity3d.com/suggestions/unityevent-dot-invoke-at-delay

9 Likes

Has anyone done any benchmarks comparing UnityEvents and standard c# delegates/events?

Just be interested to see the cost of the extra functionality.

If no one posts benchmarks, I’ll knock some out over the weekend and post here.

1 Like

Wow that is a nice feature, since in the case of C# events you have to unsubscribe in OnDisable and null check before invoking.

There’s no option for:

Yes, but I already wrote my own a year before it was released, and I don’t feel like ripping out my existing framework just to use Unity’s, especially since it lacks a few features I wrote into my own.

Ya it looks like the ngui guys had a very similar soultuon before the 4.6 days as well.

I believe they hired the guy from ngui, and that’s where they got it from.

Could you elaborate on your cutscene system? I’m working on one myself, but I’m using co-routines for scripting sequences. How are you utilizing the UnityEvents? Thanks! :slight_smile:

Understandable speculation, but off target :slight_smile: UnityEvent was in place in a branch well before that guy was briefly hired.

Why not share with the rest of us the specific feature you’d like added to UnityEvent? :slight_smile: Well worth cutting down on systems you need to maintain on your own by migrating to equivalents maintained by others, right?

It’s pretty complex at this point. There’s a cutscene manager with a custom-build UI. It allows you to add and remove different actions on a timeline. Each action is backed by an object.

When the cutscene manager starts playing, it keeps a tally of the current time since startup, and kicks off actions as it reaches their starting time.

So I can place a “move camera to x” event at 3 seconds, drag-and-drop the transform that it’s supposed to fly to into a slot in the inspector, tune how fast it’s going to move, and then the cutscene manager will make that happen 3 seconds after the cutscene starts playing.

I’m using the UnityEvents for generic events - essentially, an event in the cutscene system that wraps a UnityEvent, and fires it at it’s starting point. So if I have a canon somewhere, and want a cutscene to fire that canon, I’ll just create a generic event at that point, drag-and-drop the canon into the UnityEvent’s inspector, and have the event set off the Fire() function.

If I didn’t have UnityEvent, I would have to create a subclass of the cutscene’s event class that fired canons, and was only used in that cutscene.

2 Likes

Not when the cost of migrating is higher than maintaining my own. Or the cost of waiting for a fix to something that is of low priority to unity.

And the features are very personalized. It’s primarily a hook into a system of interfaces that I use regularly that are independent of unity as well, and integrating it into UnityEvent would be meaningless to any other user unless they were using my framework.

Nevermind adding on that fact that the ‘unity way’ is often in conflict with my own way. I probably won’t be sticking with unity much longer, but being as deep as we are with development at this point… we can’t leave it quite yet. Of course Unity5 seems to be changing a lot of habits that erk me about unity, only time will tell if they commit to it fully. Deprecating old habits can be difficult when they are well established within your community of users.

To be fair these events were only introduced in 4.6. So you aren’t too far behind the ball on picking them up. I’ve been saying since the beta came out that the inclusion of the event system was more significant then the new UI tools. But no one at Unity was making a big deal about it.

There are some other new powerful features to, including the ExecuteEvents class, that works in the other direction, allowing you to invoke methods on other scripts in a clean fashion. Knocks SendMessage out of the park.

The EventSystem component is also very powerful, enabling all sorts of magic input stuff to just happen.

3 Likes

@Kiwasi ya I really have to agree with you, UnityEvent and UnityAction were not hyped much on release and kinda views as a tool for the ui system. When they are a more important feature and are useful all over unity.

Exactly — I’d heard something about them, but it was in the context of the new UI system, but since I was pretty happy with the old UI system, I didn’t pay much attention. (I have switched to the new UI system in a new project, but will probably continue to use the old one for a long time in large existing projects.)

But yeah, UnityEvent is way more useful than just UI. It’s the decoupler the whole framework has been lacking. Like some others here, I’ve been using my own C# events and delegates, and that’s fine in code, but has the disadvantages mentioned above in this thread. Then I have my own broadcast/notification system too, which again is fine… but I’m always thinking about how to teach Unity to newbies, and how to make simple, self-contained components that are truly stand-alone, that people can just drop in and use without dragging in some big framework of support classes.

Both of those considerations make me excited to start using UnityEvent. Basically any component that does or detects something can expose a UnityEvent, enabling other components to react to this however they want. Users can hook it up in the editor, or in code, and they don’t need any other framework, they don’t need to unregister when destroyed, etc. It just works.

In our internal framework we’ve got components that send an announcement (our equivalent of UnityEvent) when they collide with something, when various Inputs are detected, when damage is dealt or received, etc. And then we have other components that react to announcements by showing/hiding/destroying the object, spawning some other prefab, sending another announcement after some configurable delay, moving or rotating the object, etc.

A library of about 20 components or so allowed my son to build this Hackenslash game with almost no custom code.

Now I’m picturing rebuilding these components around UnityEvent, and they will be even simpler, because you don’t have to code things to “react to an event” — you just have public methods that cause them to do whatever they do, and the user can hook these up to whatever events they like. And we can all share & swap such components without worrying about needing any support system; everything we need is now built in.

Brilliant!

1 Like