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)