Func and EventHandlers - when to use them?

I’ ve came across Func and EventHandler variants of delegates. Now i know that Func is used to return a type from a delegate and EventHandler is just more detailed delegate containing information about calling object.

But… do you actually have some practical uses for them? EventHandler syntax is less comfortable to work with. For return from delegate i can’t think of applicable uses. Do you have any examples for these 2?

Funcs are very specialized and are unsuitable for events, only as single cast delegates, as they have an explicit return type.

EventHandlers are a bit more complex, but outside of Unity are becoming Microsoft’s standard for events.

EventHandlers always pass the invoking object (well, generally, you could put a different object in) for every call… generally the first parameter, the sender is invoked as this
An EventHandler can be declared in several forms, and each of these changes slightly how you invoke the method, as well as the needed signature for the method. For example: A simple EventHandler that doesn’t need to pass any information to an the listeners is declared just like an Action event

public event EventHandler OnDeath;

A subscribing method would need the signature

void OnDeath(object sender, EventArgs eventArgs)

and would be invoked with

OnDeath?.Invoke(this, EventArgs.Empty);

If you just want to pass one parameter using an EventHandler, we can declare it just like we would declare an Action with one parameter

public event EventHandler<float> OnTakeDamage;

The qualifying method signature would be:

void OnTakeDamage(object sender, float amount)

and it would be invoked with the amount as the second parameter

OnTakeDamage?.Invoke(this, amount);

If you need to send MORE information, then you need to make a struct that inherits from EventArgs

public struct DamageArgs: EventArgs
{
    public float amount;
    public object DamageDealer;
    public bool fatal;
}
public event EventHandler<DamageArgs> OnHit;

The qualifying method:

void OnHit(object sender, DamageArgs args)

And it would be invoked

DamageArgs damageArgs = new() {amount = this.amount, DamageDealer = damageDealer, fatal = currentHealth<=0}
OnHit?.Invoke(this, damageArgs)
1 Like

Thanks you very much!
So event handlers other than more complex syntax, don’t differ too much from Actions and delegates?

Correct. EventHandlers primary advantage is that they are always called with the calling object. This makes them handy for static events. Consider a multiplayer game in which enemies use sound as well as sight to hunt their prey… meaning that a sound can travel through walls to aggro the enemy:

public static event EventHandler<float> OnNoiseEvent;

You might call this method in a movement script when a player’s foot touches the ground…

void RightFoot() //common Animation Event
{
    audioSource.PlayOneShot(footstepSound);
    OnNoiseEvent?.Invoke(this, 5.0f);
}

Now since all the in game NPCs have subscribed to this animation event…

void OnNoiseEvent(object sender, float intensity)
{
    if(sender is PlayerController player)
    {
         if(Vector3.Distance(player.transform.position, transform.position) < intensity)
         {
               Attack(player);
         }
     }
}

Now you might also make this sound event when firing a weapon… perhaps with an intensity of 25, enemies will hear the gunshot from a distance, even when they can’t see the player in question.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms