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