Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Can you check if an event listener exists in C# Messenger Extended?

Discussion in 'Scripting' started by Disastercake, Dec 26, 2012.

  1. Disastercake

    Disastercake

    Joined:
    Apr 7, 2012
    Posts:
    317
    I plan on using this messenger system from the wiki: http://wiki.unity3d.com/index.php?title=CSharpMessenger_Extended

    However, in psuedocode I can definitely see an issue of not knowing which event listeners have been placed in a complex class that may or may not add certain listeners. Apparently you can't just un-listen from them, as it throws exceptions, and even if it didn't crash it'd just be bad practice. Is there a way to check if an event listener has actually been added before removing it?
     
  2. hayone1

    hayone1

    Joined:
    May 20, 2017
    Posts:
    8
    I will not answer the question using the c# messenger system but use the c# events because unity supports it as StarManta pointed out(you can also use UnityEvents). Issues with subscribing and unsubscribing usually occur when you persist singletons with listeners across scenes and fill it with references to objects of different levels without unsubscribing from them when scenes are changed. So if a callback uses or alters an object that was destroyed wu=ith the previous scene there would be issues. So in case of inability to track listeners a good hack would be to set up an event Manager which is basically a class that has an event with a pointer and that obviously should be invocable somewhere and un-subscribe from them as shown below. The shortcut to preventing exceptions would be to use the catch blocks still.
    Code (CSharp):
    1. void OnEnable()
    2. {
    3.      
    4.     SceneManager.sceneLoaded += OnSceneLoaded;
    5.      try{
    6.  
    7.              EventManager.EventName1 += CallbackName;
    8.       }
    9.      catch{
    10.               Debug.log("Event already subscribed to or does not exist@ EvetName1");
    11.      }
    12. try{
    13.              EventManager.EventName2 += callbackName;
    14.       }
    15.      catch{
    16.               Debug.log("Event already subscribed to ordoes not exist @ EvetName2");  
    17. }
    18.  
    19. void OnSceneLoaded(
    20. Scene scene, LoadScenemode
    21. )
    22. {
    23.      //if this object will persist across scenes, you can remove listeners here also depending on the scene you are in
    24. }
    25.  
    26. void OnDisable()     //usubscribe from each event
    27. {
    28.        SceneManager.sceneLoaded -= OnSceneLoaded;
    29.        try{
    30.              EventManager.EventName1 -= CallbackName;
    31.       }
    32.      catch{
    33.               Debug.log("You were not subscribed to the event before trying un-subscribe. You should be subscribed to this event@ EventName1 before attempting to un-subscribe");
    34.      }
    35. try{
    36.              EventManager.EventName2 -= CallbackName;
    37.       }
    38.      catch{
    39.               Debug.log("You were not subscribed to the event before trying un-subscribe. You should be subscribed to this event@ EventName2 before attempting to un-subscribe");
    40.      }  
    41. }
     
    Last edited: Sep 4, 2019
  3. StarManta

    StarManta

    Joined:
    Oct 23, 2006
    Posts:
    8,741
    I'm struggling to figure out why you'd want to use that class over C#'s included "delegate" and "event" keywords. I would've assumed the answer was just "because Unity didn't support that version of C# yet", but you're apparently using it in 2019, so may I ask why? Does this script actually have benefits over the delegate/event keywords, or are you unaware of those keywords?

    Honestly, as a rule of thumb, anything on wiki.unity3d.com is going to be so outdated as to be worse than useless. The wiki is thoroughly unmaintained, and I've made the case before that it's doing more harm than good and should be shut down/archived. Note that the last time the front page was updated was in 2012, and that was to note a change in policy to combat spambots.... which even 7 years ago already constituted the majority of activity on the wiki.
     
  4. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    That was a hell of a necro post. Anyway. Note that you can iterate over a multicast delegate. I use this to call each delegate separately in a try. If it catches an exception the offending delegate can be removed and logged for inspection. If this really makes your messaging system failsafe is debateable. But its a start.
     
  5. hayone1

    hayone1

    Joined:
    May 20, 2017
    Posts:
    8
    I'd have to use the excuse that this is one of my early days of forming the habit of answering questions while being a beginner myself. Iteration would definitely be less painstaking and easier to maintain for a surmountable amount of delegates and just catching exceptions probably isn't the best solution to this question either.
     
    Last edited: Sep 4, 2019
  6. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,749
    Your code catches exceptions as well. Where you use them to check wether a delegate has already been added I use them to check wich ones can be removed because their object is gone. Albeit this was not the original question it may help in the mentioned scenario. Iteration could also be usefull to check if a multicast delegate contains a certain object before adding or removing it. Albeit I'm not sure if equality comparison works for delegates it could be worth a try if you need this functionality.
     
    hayone1 likes this.