Hello, i wanted to discuss about some practices i have made in my projects recently…
I discovered about Unity Events has some time, and i really loved to use them! The fact that i can add and remove any features in a dynamic and quick way is, for me, one of the biggest advantages of those events. For example, if i wanted to make a Player object that could shoot or perform a jump when i press the space bar, i can simply assign the function that i want to call in my “OnAction” event in the inspector! Here’s an example:
It works pretty well to me, but so… i started to use the UnityEvent structure in a LOT of components.
For example: i have a ColliderHandler component, where it calls an event when it collides with a object, or a DamageHandler, that calls an event when that character take damage.
My question is: there’s a drawback in using this type of pattern, like low perfomance?
I personally like this pattern a lot myself. It takes a lot of the coupling between elements of your game out of the code and into the Unity Editor. I don’t think there’s really going to be any performance problem with it.
Moving that coupling out of code and into the editor may be a drawback for some. It can make it less obvious what is triggering what and a little harder to follow the logic of A causes B causes C.
I generally like using Unity events. I’m fond of the idea of reducing code and letting non-programmers create logic. It also means I could do an update with just asset bundles (maybe a new character or map) without redeploying the binary (might take a week).
One issue I’ve had with Unity events is that they don’t show up as Visual Studio references. This creates two problems: the first is that I’ve had other programmers delete my code because they think nothing is referencing it. The other is that it makes me wary about deleting some methods because I’m unsure if it’s being used by a Unity event, so I can wind up with zombie code laying around.
Unity events also prevent Unit Testing and make networking difficult. I prefer using them for things like triggering particles and sounds.
To solve this you might want to disable the “unused” warning itself.
Here’s an example for fields (it’s another warning code in the case of a method, this is just an example)
This potential problem is true for any kind of virtual dispatch, whether you use UnityEvents, interfaces or base classes. Yes, interfaces and base class could potentially be analysed, but with normal OOP the user of a method does not know what instance it’s dealing with. So there’s no direct hard link between them.
A good solution would be to use an attribute on methods or classes do communicate intent. Attributes are just metadata and it doesn’t have to serve any purpose. However you can create a ReferencedByUnityEvent attribute and put it on methods which you intentionally want to assign to UnityEvents. Though doing this for every method would be kinda silly.
You can write some editor tool to evaluate serialized UnityEvents to reveal references
This is one of the advantages of JetBrains Rider. It knows what’s accessing UnityEvents. I’m using the built-in type in the example below but it’s able to identify custom event types too.
I don’t personally use UnityEvent since I had my own version of it predating the release of UnityEvent. But it fundamentally is very similar in how it works.
Traditionally I always just used PowerShell and/or grep to find references to things. I’ve since created an editor script like @Bunny83 mentioned that does it even easier.
One of these days I should really give Rider a full usage (I’ve dabbled in it, but that’s about it). Maybe write some extensions to support my own SPEvent alongside UnityEvent.