Delegates, Events, UnityEvents and a Basic Event Manager
Delegate Intro
I Learned about delegates today so I wanted to make a post about what i learned. A delegate acts as a container of functions. This means I can create a delegate, add other functions to it, and then by calling the delegate like a method, it will call the functions we added earlier. Define A delegate as follows.
A Delegate definition syntax is the same as when you define a method. We can then add in a bunch of functions into the delegate. They must have the same parameter types. Below are 2 example methods
You add these functions into your delegate like this
MultiDelegates
A Delegate internally is a reference pointer to a method. It allows us to treat method as a variable and pass method as a variable for a callback. When it gets called, it notifies all methods that reference the delegate. The basic idea behind them is exactly the same as a subscription magazine. Anyone can subscribe to the service and they will receive the update at the right time automatically. More info here. Here we define a delegate
Given the two functions
You can add them both into the Delegate, and execute them as follows
MultiDelegate Execution Order
But wait, if there are two methods in the Delegate, which one runs first, and is there a way to control the order? Well Microsoft says “A MulticastDelegate has a linked list of delegates, called an invocation list, consisting of one or more elements. When a multicast delegate is invoked, the delegates in the invocation list are called synchronously in the order in which they appear. If an error occurs during execution of the list then an exception is thrown.”
These means multi-delegates are run in the order they are added but!! if you need to change that, your doing something wrong. Here is a example I made adding on to first example.
MultiDelegate Issues and Events
Lets say we wanted to add 4 methods to a delegate and then call that delegate on a button press. If we messed up and had the following code
Then the delegate is overwritten. This why people use Events. “Events adds a layer of abstraction and protection on delegate, this protection prevents client of the delegate from resetting the delegate and invocation list. Events only allow to add and remove method from invocation list.”
To use a event, basically just slightly change the first two lines in the Delegate Definition. Using First code example
now you will get a error that points to the fourth line of code below. “The event ` MyDelegate’ can only appear on the left hand side of += or -= when used outside of the type `DelegateHandler”. Basically You and only use += and -=
Important Notes
When you use delegates in unity don’t forget to unsubscribe otherwise it will lead to memory leak. A good place to do this is the function OnDisable in unity. It would look like
Building A Event Manager
Now that I know what delegates and events are, lets build a event manager to help us manage events in our game. Subscribing and Unsubscribing in our game will still work the same way as above, but all events will be saved in a nice and neat EventManager Singleton. I will start by explaining two new things, UnityAction and UnityEvent. A UnityAction is very simple. It is a Zero argument delegate used by UnityEvents. Meaning it is essentially this.
Now a UnityEvent differs Slightly from the standard C# Event we had above. Further reading here. Rumor has it, that it was implemented for the new UI system in Unity 4.6, where you see it used the most often; Most notably the “Event Trigger” and the “Button” in the Unity UI Components. Heres a picture of what it looks like in the Unity Editor

As you can see we have a list shown to us of all Listeners of the event. This just makes things nicer to look at and easier to manage. Unity Events are designed hooked up at design time Or run time.
They also are a bit slower “Delegate event’s are about 38.3 time faster then UnityEvent.” But the difference is very small they are both very efficient. So it doesn’t really matter which one you use.
Now… Here is where I got confused. It seemed to me that a UnityEvent was essentially just a delegate with added features to use in the unity explorer, and that a UnityAction was also just a delegate. Before we added functions to our Delegate just with the +=. Why then do we now need two Delegates when before we only needed one and some functions?
Well I assume it to be safe as only delegates of the same type can be combined. You can see that this code has the same function as the code we had before.
Ok and one last thing for UnityEvent… Lets Do the equivalent of += and -= on it. By using the Two Delegate Version as just shown above
Ok now lets start with the singleton EventManagerClass. It basically just saves all events in a dictionary, like a dictionary of delegates. I won’t bother explaining it in detail as it is self explanatory, comments are in the code.
Final Notes
There you have it, One thing I would also like to explain is why you use a MyDelegateFunction. Invoke(); and not just MyDelegateFunction(); Heres a explanation I found online
“Ultimately they are identical. The difference is in performance and benefits. If you directly call a method then the compiler will generate the necessary code to look up the method start address in the object’s virtual table, push the parameters onto the stack and invoke the method. The runtime is ultimately responsible for dealing with this because a vtable can change depending on the object being used. Highly optimized and very fast given modern processors. This is the ideal mechanism to use. The problem is that you must know at compilation time the type being referenced, the method name and its signature. This is formally known as early binding. If the method information changes then your code won’t compile. Normally this is no problem but sometimes it is important.
This is where invoke comes in. Invoke is a late binding technique where you postpone determining a method name and signature until you are actually ready to call it. This is primarily used when you dynamically load assemblies and types and want to be able to call methods on the types. You can’t use early binding because the types were not available during compilation. Late binding basically does the same thing as early binding but it has to do it all when you call it rather than once during compilation. Therefore using Invoke is slow compared to early binding. Furthermore if you get the method information wrong then an exception will occur. The compiler can not help you at all because the method is being referenced at runtime. In general you should use invoke only when you absolutely have no idea at compilation time what a method might be. In general interfaces are used to provide a hybrid approach where you can early bind to the method but late bind to the actual implementation. Now for a .NET specific thing about invoke. Invoke is commonly used in UI code. In UI code a fundamental rule of Windows is that you can only interact with the UI on the thread that created the UI. Therefore if you want to talk with the UI on a secondary thread (such as a worker thread) you must marshal the call to the correct thread. Note that this applies to events as well. They are really nothing more than method invocations. The Control.Invoke method that is inherited by all WinForm controls allows you to call an arbitrary method on the UI thread. The method handles the process of marshalling the request to the correct thread and then calling Invoke on the method. This is still late-binding even though you know in advance what method you wanted to call.
Where do delegates come in? To provide some level of compiler checking for you many method that will ultimately use invoke require that you specify a delegate as a parameter. By requiring that you pass a delegate the compiler can enforce that you are passing a method that actually exists and that contains the parameters that the eventual invoke will use. A delegate is really nothing more than a mechanism of specifying at compilation time the required signature of a method. Delegates are almost always used with invoke to provide some compile-time safety. For example when you create a worker thread you will pass a delegate of type ThreadStart. This delegate will map to a method that you defined and that has the appropriate signature. This alleviates the thread code from having to verify that the method you specified exists and that the parameters match. If you get it wrong it is a compile time error. However the thread class will still use invoke to call your method because when the thread class was written your method did not exist yet.”