I was wondering which are do you prefer/use in your games? To be honest, I have always used c# events - I was a c# programmer before I started Unity. However, I am intrigued by UnityEvent.
I know UnityEvent has the advantage that it can be visually modified through the editor and also serialized. So you can set up receivers in the editor.
How about performance? Is UnityEvent using c# delegates under the hood? Or some kind of reflection or even the hated SendMessage method?
Using c# events we have to be careful with garbage collection. How about UnityEvent?
UnityEvent uses weak references so you don’t have to worry about dangling references.
Under-the-hood details are sparse, but speculation is that UnityEvents probably have a bit more performance overhead than C# events. (I would wager that it’s not enough to matter, though.)
And yeah, the serialization and editor support is a big one. I would say that if you’re hooking something up entirely in code, with things you don’t want exposed in the editor anyway, then go ahead and use C# events. They’re typesafe and can more clearly express the contract between the sender and the receiver. But if you think there’s any chance that a level designer (including yourself) might someday want to do something else when this event happens… activate or deactivate some other object, start/stop an animation, play a sound, whatever… then a UnityEvent makes all that possible, without having to write or modify code.
Might be. I would suggest that your health script, whenever it takes some damage, invoke a “damageTaken” event. (And it should probably also expose some other events for healed, dead, etc.)
Then you can easily hook up things like sound effects, animations, etc. to the fact that the player’s taken some damage.
However, for the actual health bar (or similar display), I’m not so sure if a generic UnityEvent is appropriate. You might want to define an event that takes a float parameter (as described here and here for example), and invoke it with the amount of health left. That way, the receiving method gets all the info it needs to update its display, and doesn’t have to go looking for it via some other connection.
Ya could have damage taken event include data for the amount of damage, as well as healed etc. Things like sounds that don’t need that data can ignore it, things that want the data can use it.
Yeah, Im currently doing that at the moment with c# events. The Ui scripts just find the player game object (its a singleton) and subscribes to various events in the good old += notation. I dont have to worry about dangling references as the UI and the game object will never be destroyed.
Code example:
public event DamageReceivedEvent OnDamaged;
public event DeathEvent OnDeath;
protected void HandleEffect(Effect e)
{
switch (e.StatChange.Stat) {
case Stat.HEALTH:
Health += e.StatChange.Value;
if(e.StatChange.Value < 0)
{
InvokeDamageReceived(e, +e.StatChange.Value);
}
if(IsDead)
{
InvokeDeath();
}
break;
}
}
protected void InvokeDeath()
{
if(OnDeath!=null)OnDeath(this);
}
protected void InvokeDamageReceived(Effect e, int damageAmount)
{
if(OnDamaged != null)OnDamaged(this, e, damageAmount);
}
I mean this is fine and it works. But if I can allow designers to just hook up to the damage event in the editor it feels better for them. If they just have to add a method to their scripts and the assign it in the editor as a receiver and not care about finding the player, and in the case of short lived objects, not worrying about references I think it would be better.
Gah… maybe I UnityEvent is just a solution looking for a problem/use in my project.
Yeah, I think when you’re primarily a coder, the advantages of UnityEvent are fairly small. Good ol’ C# delegates and events are not too hard to use, and standard in the language, which means a lot of developers already know how to use them.
UnityEvents are a big win when you want to hook things up in the inspector, though.
Rather than C# events, I’ve been using Unity’s new messaging system, which provides the advantages of C# interfaces and events but works better (in my opinion) for MonoBehaviours.