Search Unity

ExecuteEvents vs. doing it yourself

Discussion in 'Scripting' started by JoeStrout, Nov 28, 2015.

  1. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    I've been trying to embrace Unity's new(ish) "messaging system" as much as I have embraced UnityEvent. But I'm finding it rather more awkward, and no more powerful, than doing what it appears to do the old-fashioned way. I'm looking for feedback on what I'm doing, and anything I may be missing.

    So, let's say I have a turn-based game, and my objects may have components that need to know about the start of a turn. So I define an interface:

    Code (CSharp):
    1. public interface IStartTurnTarget : IEventSystemHandler {
    2.     void StartTurn();
    3. }
    And then, when I want to invoke that StartTurn method on any components of an object that may implement it, I do:

    Code (CSharp):
    1. ExecuteEvents.Execute<IStartTurnTarget>(gob, null, (x,y)=>x.StartTurn());
    But I find this syntax hard to remember and annoying to type, so I wrap it in a little helper method in a static module I create just for this purpose...

    Code (CSharp):
    1. public static class Messages {
    2.  
    3.     public static void StartTurn(GameObject gob) {
    4.         ExecuteEvents.Execute<IStartTurnTarget>(gob, null, (x,y)=>x.StartTurn());
    5.     }
    6.  
    7.     // ...and others like it here
    8. }
    OK, great, so now I can call Messages.StartTurn(gob) to invoke the StartTurn method on components of gob.

    But the thing is, I can do exactly the same thing by defining my static method this way:

    Code (CSharp):
    1.     public static void StartTurn(GameObject gob) {
    2.         foreach (var target in gob.GetComponents<IStartTurnTarget>()) {
    3.             target.StartTurn();
    4.         }
    5.     }
    And use this helper method in exactly the same way. But in this case, my interface doesn't need to derive from IEventSystemHandler, and I don't have all that extra cruft (null, (x,y), etc.) in the invocation.

    If I were going to dispense with the helper method and invoke these things directly... well, in that case the ExecuteEvents code is only one line instead of three, but it's one difficult & obtuse line, instead of three very clear & obvious lines. I'd just as soon have the latter.

    And I realize that there is ExecuteEvents.ExecuteHierarchy, to work its way up the chain looking for an implementor, but we could just do gob.GetComponentsInParent (and even get to choose whether to include inactive components!). Similarly, if we want to invoke the method for all descendants, we would just use GetComponentsInChildren. So again, the clear, simple code is at least as powerful as ExecuteEvents, if not more.

    So. Are there any compelling reasons to use Unity's messaging system?
     
    Favo-Yang likes this.
  2. BenZed

    BenZed

    Joined:
    May 29, 2014
    Posts:
    524
    According to the docs, they created this messaging system for the new UI. Since UI's can often contain hundreds of behaviours that could respond to events, Perhaps ExecuteEvents.Execute is more performant than the GetComponent alternatives?
     
  3. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    Possibly — it's true that I haven't done any performance tests. It's conceivable that ExecuteEvents does some sort of caching to avoid the search that GetComponents requires. But it could be tricky to keep this up to date as components might be added or removed... I suspect that it's just using GetComponents under the hood.
     
  4. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    I would be surprised if there was any caching going on, but you could always bench mark it to find out.

    If you are not passing in any event data I'm not sure that there is much of a benefit to ExecuteEvents. It might be useful if your closure was more complex.