Search Unity

Events, is it a proper approach?

Discussion in 'Scripting' started by SoulGameStudio, Aug 30, 2016.

  1. SoulGameStudio

    SoulGameStudio

    Joined:
    Jan 18, 2016
    Posts:
    46
    Hey there,

    Following tutorials and forums, I've been taught to use events this way:
    Code (CSharp):
    1. public delegate void OnActHandler(Fighter pFighter);
    2. public event OnActHandler OnAct;
    3. public delegate void DieHandler(Fighter pFighter);
    4. public event DieHandler OnDie;
    5. public delegate void OnDisappearHandler(Fighter pFighter);
    6. public event OnDisappearHandler OnDisappear;
    But it quickly becomes heavy and repetitive. But then I just came up with this approach:
    Code (CSharp):
    1. public delegate void FighterHandler (Fighter pFighter);
    2. public event FighterHandler OnAct;
    3. public event FighterHandler OnDie;
    4. public event FighterHandler OnDisappear;
    What do you think? Is it okay to share an handler or does it completely breaks the purpose of it all? I'm uncertain if I should start using that simpler approach or not.

    Thanks!
     
  2. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    wouldn't the only thing "wrong" with the second approach be all 3 events have the same effect (calling the one delegate)... if you want all 3 events to do the exact same thing, sure, why not.
     
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    The fast way to use events is through Action and Func:

    Code (csharp):
    1. public Action<Fighter>OnAct;
    2. public Action<Fighter>OnDie;
    3. public Action<Fighter>OnDissapear;
    ;

    Action<T> is a void delegate, and Func has a return type.


    I generally only write out the name of the delegate like you're doing if the name of the delegate is going to relay information. The word "FighterHandler" doesn't say much of interest, so I think using eg. Action<Fighter> OnDie is more than enough to convey what you're trying to do.
     
  4. SoulGameStudio

    SoulGameStudio

    Joined:
    Jan 18, 2016
    Posts:
    46
    @LeftyRighty Thanks. And yeah, the only true difference between all those events are when they are fired, and what happens when they are caught.

    @Baste Oh nice to know I can subscribe to Action, I didn't know that. Since the result is the same, I think I'll keep the common void delegate approach, it seems more "clean" and generic to me. Beside, subscribing to Action, hide the key word "event"; and is a bit confusing, isn't it?

    Thanks for the inputs, that helps clearing the air :)
     
  5. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,741
    Code (CSharp):
    1. public event Action<Fighter> OnAct;
     
    Last edited: Aug 30, 2016
    SoulGameStudio likes this.
  6. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    418
    Last edited: Aug 30, 2016
    SoulGameStudio likes this.
  7. SoulGameStudio

    SoulGameStudio

    Joined:
    Jan 18, 2016
    Posts:
    46
    @IsaiahKelly Quite interesting, I didn't know Unity had his own Event system (how the hell did I miss that o_O), I'm looking into it, see if it would suits me better. Thanks for sharing!
     
  8. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,528
    The delegate is just the type of the event. It doesn't really need to convey any more information than the shape of the method.

    It's the 'event' that makes it an event. And it's the name of the event that says what it does.

    Like passerbymc wrote:
    Code (csharp):
    1.  
    2. public event Action<Fighter> OnAct;
    3.  
    Note... all the 'event' portion says is that the methods can only be called from the scope of the owning type. So if class 'Foo' has an event 'Foo_OnAct', then only code written in 'Foo' can raise 'Foo_OnAct'.

    Where as if you just had a delegate reference, like in Baste's code. ANYONE could call it, since it's a public member. All that is needed is a reference to the owning object.

    Also, the .Net standard prefers an event shape that is:

    void (object sender, EventArgs e)

    where variations of it change out EventArgs with a type that inherits from EventArgs.

    But of course, that's just a .Net standard... and not a requirement. In Unity people generally ignore it.

    The nice thing about that shape though is that no matter the event args, a generic method that meets those minimum requirements can always register for an event.
     
  9. SoulGameStudio

    SoulGameStudio

    Joined:
    Jan 18, 2016
    Posts:
    46
    @lordofduct Thanks for the details and further notes, I appreciate the one about the scope which is pretty important to me. The thing about the .NET standard is that it is pretty heavy to my taste, and useless in 90% of my cases where my event have no params at all, and are just triggers. Well, maybe someday when I'll go 100% industrial coding :p
     
  10. makeshiftwings

    makeshiftwings

    Joined:
    May 28, 2011
    Posts:
    3,350
    Then you can just do:
    Code (csharp):
    1. public event Action OnWhatever;
    I pretty much always use "Action" and "Func" and haven't used the "delegate" keyword or named delegate types in forever.
     
  11. IsaiahKelly

    IsaiahKelly

    Joined:
    Nov 11, 2012
    Posts:
    418
    Yeah, it seems like most people don't and it's a real shame because they're super powerful and useful.

    For example, you could create a health script and give it an OnDamaged UnityEvent like this:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Events;
    3.  
    4. public class Health : MonoBehaviour
    5. {
    6.     public float health = 100;
    7.     public UnityEvent OnDamaged;
    8.  
    9.     public void TakeDamage(float damage)
    10.     {
    11.         health -= damage;
    12.  
    13.         if (OnDamaged != null)
    14.             OnDamaged.Invoke();
    15.     }
    16. }
    This will then display the UnityEvent OnDamaged in your script's inspector, where you can subscribe any public function to the event without writing any code! This is the same system used by the Unity UI system to hookup UI logic in the editor.

    UnityEvents.png
     
    Last edited: Aug 30, 2016
    SoulGameStudio likes this.