Search Unity

Resolved Event sequencing done right?

Discussion in 'Scripting' started by MostNimbus, May 9, 2020.

  1. MostNimbus

    MostNimbus

    Joined:
    Dec 21, 2016
    Posts:
    15
    In attempts to make my life easier, I, alas, have only made it harder.

    I needed to create an event sequencing system without using coroutines due to the restrictions created by myself. I ended up using Actions to track when do events start and end:

    Code (CSharp):
    1. public class EventBase
    2. {
    3.     public Action OnEventStart;
    4.     public Action OnEventEnd;
    5.      
    6.     public virtual void EventStart() { OnEventStart?.Invoke(); }
    7.     public virtual void EventEnd()   { OnEventEnd?.Invoke();   }
    8. }
    9.  
    But then I need to cycle through a list of events, starting the next when the previous ends

    Code (CSharp):
    1. void SequenceEvent(EventBase currentEvent)
    2. {
    3.     curEvent++;
    4.     EventBase nextEvent = curEvent < eventList.Count ? eventList[curEvent] : null;
    5.     if (nextEvent != null)
    6.     {
    7.         currentEvent.OnEventEnd += () => SequenceEvent(nextEvent);
    8.     }
    9.     currentEvent.EventStart();
    10. }
    11.  
    And then I clear subscribtions after the event has ended, with a catch, because I used lambda expression so now I resort to this

    Code (CSharp):
    1. private void ResetInvokations()
    2. {
    3.     OnEventStart = null;
    4.     OnEventEnd = null;
    5. }
    6.  
    And technically it does work but I get a crippling feeling that it could be done much better and more efficiently than constantly subscribing and nulling actions. If you got any critique or tips regarding this I'm all in.
    Thanks
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    The big problems I see is that your ResetInvokation is going to clear ALL registered handlers, and not just the one you're concerned with. This could potentially blow out things that didn't expect to be. This is actually why the 'event' modifier exists and does what it does... the 'event' modifier makes it where only the type who declared the event can null out the event or invoke the event. While all others can only +/- with the event to register/unregister. Rather than just having it public and modified/called willy nilly.

    Anyways... you could just not use a lambda to chain the 'SequenceEvent', and just have a private handler that does it instead. You would have to store the next state somewhere of course... or you could make it where OnEventStart/OnEventEnd passes in itself as a parameter. To refer back to C# events again, this is why System.EventHandler<T> is shaped the way it is... it always includes "sender" and "eventargs". The "sender" is the object that dispatched the event, and the args are any related information you may want for the event (you don't have args in your case... but the 'sender' is definitly useful):
    https://docs.microsoft.com/en-us/dotnet/api/system.eventhandler-1?view=netcore-3.1

    Also, why not just register said event when the eventbase is added to the collection? No need to register/unregister over and over. They shouldn't be firing anyways... and since you're going to keep track of which event you're on, if one misfires you can suss that out (and actually react to that in some way, debug out why it's happening).
     
  3. MostNimbus

    MostNimbus

    Joined:
    Dec 21, 2016
    Posts:
    15
    That sounds like the best solution. Thanks.

    Also, sorry for my poor API knowledge but how should I handle new entries in the list? It's serialized and modified through inspector but I can't find any built-in handlers.