Search Unity

Event System - Dispatcher

Discussion in 'Assets and Asset Store' started by Tryz, Dec 6, 2015.

  1. Ylor

    Ylor

    Joined:
    Dec 15, 2014
    Posts:
    16
    Hi!

    I'm trying out your messagning system for a project. I have a question, though: Most of my messages are listened to by many objects. For this reaon I haven't implemented any "message handled" code - since the message might be needed for many more objects. Also, sometimes there may be no listeners in play, subscribing to a certain message. Both these situations generate a lot of Warnings about there being unhandled messages. Is this something I should be concerned with? Does not setting a message as handled have any implications (like they stack up in memory or something)? Or can I just comment out the Debug.LogWarning writing all these warnings, since they are not interesting to me?

    Cheers
    Rasmus
     
  2. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    No, it's not an issue. Messages aren't backed up or chewing up memory.

    What you can do, is assign a handler for non-handled messages. Then, I'll stop sending the warnings.

    What I mean by that is to do something like this:

    Code (CSharp):
    1. MessageDispatcher.MessageNotHandled = OnMessageNotHandled;
    2.  
    3. /// <summary>
    4. /// Raised when there are no listeners for the message
    5. /// </summary>
    6. /// <param name="rMessage"></param>
    7. public void OnMessageNotHandled(IMessage rMessage)
    8. {
    9.       // Do nothing
    10. }
    This way you don't have to modify my code. :)

    I'll also add that even if you don't do this, I only write those warnings in the editor. I don't do that in a build.
     
  3. Ylor

    Ylor

    Joined:
    Dec 15, 2014
    Posts:
    16
    Thank you! Sorry for late reply - I forgot to check it and just left the warnings for the time being. I'll try your solution!
     
    Tryz likes this.
  4. Victor_Kallai

    Victor_Kallai

    Joined:
    Mar 5, 2014
    Posts:
    123
    Hello, I want to use this in my next project, but I do not like the fact that it's not type safe, you have to cast the Data property to whatever you want to send with the event.
    I'm thinking about adding Generics to the iMessage interface, and the Data property should be the type of the Generic.

    Let me know if you plan to add this, or if you have any ideas.
     
  5. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    You can also create your own custom message type. I show an example of that with "MyCustomMessage.cs" that is included in the "Demos\Scenes" folder.

    This way you can ignore "Data" and create your own type-safe properties.

    I don't plan on creating a separate generics message, but you could do it with with a custom message.
     
    Victor_Kallai likes this.
  6. meigo

    meigo

    Joined:
    May 21, 2014
    Posts:
    1
    Hi,
    when additively loading scenes (using SceneManager.LoadSceneAsync with LoadSceneMode.Additive in my case), a new message dispatcher will be added with each load. How could I prevent this? Thanks.


    EDIT:
    Cause of this problem seems to be outside of message dispatcher code, a simple test project behaves as expected. So I have to investigate further. Thanks Tim for a quick reply!
     
    Last edited: Dec 12, 2017
  7. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Hey @meigo ,

    I'm not seeing this. I created 3 different scenes and I'm adding them with this code:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3.  
    4. public class AdditiveScenes_code : MonoBehaviour
    5. {
    6.     void Update ()
    7.     {
    8.         if (UnityEngine.Input.GetKeyDown(KeyCode.Alpha0)) { SceneManager.LoadSceneAsync(0, LoadSceneMode.Additive); }
    9.         if (UnityEngine.Input.GetKeyDown(KeyCode.Alpha1)) { SceneManager.LoadSceneAsync(1, LoadSceneMode.Additive); }
    10.         if (UnityEngine.Input.GetKeyDown(KeyCode.Alpha2)) { SceneManager.LoadSceneAsync(2, LoadSceneMode.Additive); }
    11.     }
    12. }


    I wouldn't expect multiple stubs to be added because it is a static field in the MessageDispatcher (line 44). Unity wouldn't run that code multiple times.

    Can you send tim@ootii.com a small sample project that is doing this? Thanks.

    [EDIT] Please include your Unity Order ID too. This way I can track who I provide support to. Thanks!
     
    Last edited: Dec 11, 2017
  8. MaliceA4Thought

    MaliceA4Thought

    Joined:
    Feb 25, 2011
    Posts:
    406
    Hi :) okay now I am into messages :)

    So following instructions (I think)..

    I set a listener like this..
    Code (CSharp):
    1. MessageDispatcher.AddListener("SpellUsed", "manacost", OnSpell);
    Then I set a despatcher from another script like this..
    Code (CSharp):
    1.             Debug.Log("sending mana " + manaCost.ToString());
    2.             MessageDispatcher.SendMessage("SpellUsed", manaCost.ToString());
    In the Listener script I have the following :-
    Code (CSharp):
    1.         public void OnSpell(IMessage mMessage)
    2.         {
    3.             Debug.Log(" Got Spell Message");
    4.             Debug.Log((string)mMessage.Data);
    5.          }
    The despatcher sends the debug log message correctly of sending mana 20

    The Listener never fires the OnSpell().

    I guess I'm not getting this yet :)

    M
     
  9. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    You're close. :)

    For the listener, you are listening for message type of "SpellUsed" and a filter of "manacost". Think of them as two conditions that are required. I do this because typically the filter would be an object name or tag.

    In the dispatch, you're sending just the message type and manaCost is being thought of as the filter (since it's a string)... which isn't "manacost". They don't match so OnSpell() isn't called.

    Change your listener to this:
    MessageDispatcher.AddListener("SpellUsed", OnSpell);

    Now you're not using a filter.

    The second issue is that your data is a string and getting caught up in the SendMessage functions as a filter value (C# is thinking it's filter).

    So, we'll be explicit about the call.
    Code (CSharp):
    1. // Create the message
    2. Message lMessage = Message.Allocate();
    3. lMessage.Type = "SpellUsed";
    4. lMessage.Data = "12";
    5.  
    6. // Send it or store it
    7. MessageDispatcher.SendMessage(lMessage);
    8.  
    9. // Free up the message since we created it
    10. lMessage.Release();
    Now OnSpell() is called and you can display the data as "12".

    The one-liner SendMessage works well if you're not sending data or if your data isn't confused by C# as another argument (string = filter and float = delay).
     
    MaliceA4Thought likes this.
  10. MaliceA4Thought

    MaliceA4Thought

    Joined:
    Feb 25, 2011
    Posts:
    406
    Awesome :) TY :) Job done.. Can think of SO many uses for this in the game to make life easier for a non coder like me :)

    Regards

    M
     
    Tryz likes this.
  11. jim00

    jim00

    Joined:
    Feb 1, 2015
    Posts:
    57
    How to I get the MaxHealth from the Listener side?

    I try Print to Console using the following code but all give me error:
    Code (CSharp):
    1. void Start () {
    2.         MessageDispatcher.AddListener("CUSTOM", OnRecdMsg, true);
    3.     }
    4.  
    5.     private void OnRecdMsg(IMessage rMessage) {
    6.         Debug.Log((string)rMessage.Data + " " + rMessage.Type);
    7.  
    8. //Error:
    9.         //print(rMessage.Type + rMessage.MaxHealth);
    10.         //int myMaxHealth = ((MyCustomMessage)rMessage).MaxHealth;
    11.         //print(myMaxHealth.ToString());
    12.  
    13.     }

    Code (CSharp):
    1. MyCustomMessage
    2. lMessage = MyCustomMessage.Allocate();
    3. lMessage.Type = "CUSTOM";
    4. lMessage.MaxHealth = 100;
    5. lMessage.CurrentHealth = 50;
    6. lMessage.Sender = this;
    7. lMessage.Data = Color.blue;
    8. lMessage.Delay = 1.0f;
    9. MessageDispatcher.SendMessage(lMessage);
     
  12. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Hey @jim00 ,

    In the Demos folder, there's a UI.cs file that uses MyCustomMessage. The OnCustomMessageReceived function looks like this:

    Code (CSharp):
    1. /// <summary>
    2. /// Raised when we get the custom message
    3. /// </summary>
    4. /// <param name="rMessage">Customized message</param>
    5. public void OnCustomMessageReceived(IMessage rMessage)
    6. {
    7.     int lMaxHealth = ((MyCustomMessage)rMessage).MaxHealth;
    8.     int lCurrentHealth = ((MyCustomMessage)rMessage).CurrentHealth;
    9.  
    10.     string lString = lCurrentHealth + " of " + lMaxHealth + " health";
    11.  
    12.     MyCustomMessage.Release(rMessage);
    13. }
    You will get an error with your line #9 in the first block because the IMessage doesn't know about MaxHealth. However, you're doing it right on line #10 by casting IMessage to MyCustomMessage.

    I hope that help.
     
    hopeful likes this.
  13. DIMarshall

    DIMarshall

    Joined:
    Nov 21, 2016
    Posts:
    2
    I love this plugin! it makes everything so much easier!

    Is there a way to get a list of registered event types and filters from the Dispatcher. I made myself a command interface and it would be nice to see a list of everything registered. Not only to troubleshoot registration, but also to save time making test buttons when I can just type/click on the event.
     
    Tryz likes this.
  14. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Hey @DIMarshall ,

    I don't have a way to extract that, but you could probably extend the MessageDispatcher.cs to get what you want. There's a nested dictionary called mMessageHandlers that holds all the handlers.

    The first key (string) is the "Message Type" the second key (string) is the "Filter". If you cycle through those, that may help.
     
  15. DIMarshall

    DIMarshall

    Joined:
    Nov 21, 2016
    Posts:
    2
    That's what I was thinking. I wanted to check and see if there was a way without altering your code. I'll switch that from private to protected so I can read it with an extension script and set a remark up to change it back whenever I update.
     
    Tryz likes this.
  16. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    If you want, feel free to send me your changes. If they look like something others could use, I'll add it to the asset and make it part of the package going forward. This way, you don't have to make changes during updates.

    But... I totally understand that it's not your responsibility to create features for my assets. So, it's totally up to you. :)
     
  17. jim00

    jim00

    Joined:
    Feb 1, 2015
    Posts:
    57
    If you want, feel free to send me your changes. If they look like something others could use, I'll add it to the asset and make it part of the package going forward. This way, you don't have to make changes during updates.

    But... I totally understand that it's not your responsibility to create features for my assets. So, it's totally up to you. :)


    I would like to see that as a feature in your future update. Would that be possible? ;)
     
    Tryz likes this.
  18. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402


    Before updating, PLEASE READ THIS!

    This update REQUIRES that you delete your 'Assets\ootii' folder and re-import the assets.

    Today I'm pushing up a massive update to all my assets. The primary goal is to support Unity's Assembly Definition Files, but there's some other cools stuff as well:

    1. Assembly Definition File support
    2. Restructure folders so demo files are in one place (easy to remove)
    3. Smaller download size

    Please back-up your project and wait for all my assets (that you own) to be updated by Unity. :)

    As always, I'm here to help.
     
    stylophone and hopeful like this.
  19. SpyrosUn

    SpyrosUn

    Joined:
    Nov 20, 2016
    Posts:
    144
    Hi there, nice asset ! I am really close to buying this one, but I had a question to see whether it would be a good fit for my type of events.

    In my scene, I have, say 50 sprites of type Monster, all of which I want to add an onclick listener to(passing arguments too). I know that I can use a normal onclick listener, like "sprite.onClick.AddListener(....)", but I want to have a more clear syntax and decouple the actual methods. Probably setting the listeners on the levelManager script and then have like a Monster class that will be responding to those onClick events. Would a UIButton.Onclick type event work here ?

    While i've seen that the asset handles keypresses, not sure if it actually would handle UI onclick events that are dynamically generated via code.

    Could you help by clarifying that ? Thanks !
     
  20. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    All of this asset is raw code based. So, you would have your monsters use AddListener(). Then, you would write code to capture an OnClick or OnKeyPress or anything. In that code, you would call my SendMessage() function with the message you want.

    So, it can do things with clicks or anywhere that you call SendMessage().

    I hope that makes sense.
     
  21. SpyrosUn

    SpyrosUn

    Joined:
    Nov 20, 2016
    Posts:
    144
    Awesome, yes, that's what i wanted, just integrate all my events with it, so that I have a common events framework. Bought it, thanks !
     
    Tryz likes this.
  22. DanielKW

    DanielKW

    Joined:
    Nov 11, 2014
    Posts:
    38
    @Tryz I was wondering, I just downloaded the asset to my project(bought it awhile ago) just trying it out for the first time today.

    What files can i add to my .gitignore, safely without breaking the asset. Because I don't want to redistribute any files that aren't necessary for it to run, and violate the asset store TOS.

    P.S It's a private git repo if that helps.
     
  23. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Anything in the _Demos isn't needed. Everything else would be.
     
  24. qkjosh

    qkjosh

    Joined:
    Nov 29, 2015
    Posts:
    33
    Hi there! Just wondering if there could be an option to use unscaled time when sending a message. My use case is sending a delayed message inside a pause menu, when Time.timeScale is set to zero.
     
  25. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Unfortunately, I use Time.deltaTime at the core for determining the delay of messages. I do that at line 657 of MessageDispatcher.cs.

    If you want to customize the delay, my suggestion would be to hold onto a reference of the message and then send it immediately when your unscaled time has completed. Basically, you would managed any of the delay you want.

    I hope that helps.
     
  26. qkjosh

    qkjosh

    Joined:
    Nov 29, 2015
    Posts:
    33
    Right, I checked the source code and found that; I guess I was hoping for the ability to pass whether Time.deltaTime or Time.unscaledDeltaTime gets used there as another parameter so I can decide on a message-by-message case. I understand this might be a niche request, though, so I'll just handle the delay on my own.

    Edit to clarify: even though I'm delaying the message, the intent is still to send it say, 1 second later, while time scale is still zero. Current workaround is to send the message immediately, which doesn't rely on deltaTime, but have that message call a coroutine running on unscaled time. It's a little bit clunky, though.
     
    Tryz likes this.
  27. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
  28. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    I just replied to your email.

    You're right. It's not a feature that exists today, but I'll add it to my wish-list.

    Thanks!
     
    jGate99 likes this.
  29. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,945
    @Tryz

    I liked the support of custom messages, but is there any way or ideas to avoid casting?

    Code (CSharp):
    1. public void OnCustomMessageReceived(IMessage rMessage)
    2. {
    3.     int lMaxHealth = ((MyCustomMessage)rMessage).MaxHealth;
    4.     int lCurrentHealth = ((MyCustomMessage)rMessage).CurrentHealth;
    5.  
    6.     mCustomMessageResult = lCurrentHealth + " of " + lMaxHealth + " health";
    7.  
    8.     MyCustomMessage.Release(rMessage);
    9. }
    For example is there any way of doing this?

    Code (CSharp):
    1. public void OnCustomMessageReceived(MyCustomMessage rMessage)
    2. {
    3.     int lMaxHealth = rMessage.MaxHealth;
    4.     int lCurrentHealth = rMessage.CurrentHealth;
    5.     MyCustomMessage.Release(rMessage);
    6. }

    Something like this
    https://github.com/GalvanicGames/unity-events

    please advise
     
    Last edited: Dec 9, 2018
  30. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    I don't believe so. Since I'm looking for listeners with IMessage, that's what goes into my caches.
     
  31. nickfourtimes

    nickfourtimes

    Joined:
    Oct 13, 2010
    Posts:
    219
    I'm using the plugin in our project, and every once in a while when we exit Play mode we notice a new MessageDispatcherStub GameObject in our scenes. This object has a script component on it, but "The associated script cannot be loaded. Please fix any compile errors and assign a valid script." This though there aren't any errors reported in the console.

    I notice the following line in MessageDispatcher.cs
    Code (CSharp):
    1.  
    2. #pragma warning disable 0414
    3.         private static MessageDispatcherStub sStub = (new GameObject("MessageDispatcherStub")).AddComponent<MessageDispatcherStub>();
    4. #pragma warning restore 0414
    However, there's no corresponding MessageDispatcherStub.cs. I'm on the latest release from the asset store.
     
  32. nickfourtimes

    nickfourtimes

    Joined:
    Oct 13, 2010
    Posts:
    219
    Apologies for the bump, I just realised I should probably tag @Tryz
     
  33. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Hey @nickfourtimes ,

    I've been answering posts on the weekends. Just not enough time on the weekdays. ;)

    The MessageDispatcherStub is in the MessageDispatcher class (at the bottom). Since it isn't created at edit time, having it inside the MessageDispather.cs has been fine.

    I've not seen the message you're talking about. Since that line is in the class declaration as a static property, it would only be created when the static class is instantiated. Are you creating an instance of the MessageDispatcher at edit-time?

    The only other time I think it could run is if you compile your code while running. That might create an instance, but should be rare.

    No one else has reported this one either. So, I'm trying to think what might be different about what you're doing. Does this happen to you in my demo scene?
     
  34. nickfourtimes

    nickfourtimes

    Joined:
    Oct 13, 2010
    Posts:
    219
    Oh right, I see MessageDispatcherStub now. Could've sworn I'd searched for the declaration before but... anyway.

    It's always been difficult to replicate the problem, so I can't say for sure what's causing it. I do know that I'm only using the dispatcher in a few places, and searching through everything just to be sure I can see that all I'm using is MessageDispatcher.{Add|Remove}Listener() and MessageDispatcher.SendMessage(). Nothing out of the ordinary, I don't think.

    Earlier today I could hit Play in the editor, see MessageDispatcherStub appear in the DontDestroyOnLoad scene, then switch to another scene before leaving Play mode... then returning to the original scene, the stub would be present (with the error message on the stub component). However, I'm doing that again now, and the stub is being deleted and is not persisting, as expected.

    Well, I'll keep an eye out and see if there's some reliable way to make this happen. Will write again if I find anything; otherwise, thanks for the suggestions.
     
    Tryz likes this.
  35. cryogee

    cryogee

    Joined:
    Aug 6, 2009
    Posts:
    132
    Hi

    Im getting namespace cannot be found error!
    How to fix that

    Are there any additional setups besides just importing the package?

    Yogee
     
  36. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Nope. Just import the package.

    I just did and didn't have any issues. No one else has reported the issue either.

    Try importing into a brand new project to ensure some other asset isn't conflicting.
     
    hopeful likes this.
  37. Duffer123

    Duffer123

    Joined:
    May 24, 2015
    Posts:
    1,216
    @Tryz ,

    Just purchased this Asset.

    Looks like it's going to be v helpful.

    One thought I wondered about... What about a RepeaterSendMessage that repeatedly sends the Message every xxx seconds until handled or cancelled? Useful for buff and debuffs effects etc? Just an idea...
     
  38. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Hi. I like the idea and will add it to the wish list. However, it's not something I will get to for a while.

    You could actually create a component that tracks the messages and resends them until the IsHandled property is set. That might hold you over.
     
    Duffer123 likes this.
  39. Duffer123

    Duffer123

    Joined:
    May 24, 2015
    Posts:
    1,216
    Excellent. Thanks Tryz for the quick response as ever.
     
  40. cryogee

    cryogee

    Joined:
    Aug 6, 2009
    Posts:
    132
    Behaviour was due to .asdef files. I deleted all the asdef files and now the errors are gone and I was able to use the sample code.

    Do you see any issues with deleting all asdef files in this package and using it?
     
  41. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Deleting the .asdef files is fine. Unity just won't put them into their own space (think DLL).

    It's odd it game you issues though. I'll have to look into it.

    For now, deleting the .asdef files is perfectly fine.
     
  42. cryogee

    cryogee

    Joined:
    Aug 6, 2009
    Posts:
    132
    Main Screen -> Gameplay Screen

    I added a listener for each character in Character Select Screen Script in Main Screen in Start Method
    When i come back from gameplay screen, these listeners are added again.

    Which was causing the null errors as I think previous transform was null.

    So I added listener in Enable and removed them in disable.

    Are we expected to manage add/remove or null transforms can be ignored/removed automatically?
     
  43. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    You have to manage them.

    Unity doesn't report when an object becomes null. If I were to check it every frame it would take too much time. So, you'll want to manage your objects yourself.
     
  44. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Hi, I have a question.

    What happens when an object with the listener gets destroyed?

    Does the listener gets automatically removed? Or do we have to remove the listener manually prevent unnecessary polusions?

    If we have to remove them manually in OnDestroy(), it's bit tedious and I think automatic removal is possible.
    One cheap possible way is to add a remove listener callback to destroy message whenever we add a listener.

    Thanks.
     
  45. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Hi @chrisk ,

    When you destroy an object, you'll need to destroy any listener that it may implement.

    I don't hold a reference to the object, just the function you use as the handler. In order to improve performance, I don't constantly check if the handler functions are valid... I assume you're managing them. You could certainly add code into your object's OnDisable or OnDestroy method to remove the listener.

    I think it's safer for you to manage how that's done.
     
  46. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    I see. You will almost certainly want to remove the listener when an object is destroyed.
    I can't think of reason you want to keep the listener on destroyed object.
    This means that you have to add RemoveListener for every AddListener in Destory().
    This is very tedious.

    That's why I asked if it can be automatized by adding RemoveListener to OnDestroy event when AddListener is called.

    thanks.
     
  47. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    I agree. I don't believe we would want to keep a listener on a destroyed object.

    However, I don't know if you use pooling or factories or some other method to manage your GameObjects. So, it's best if you remove the listener based on your setup.

    Unity does not have a way to do this.

    There is nothing in Unity that will automatically notify the Dispatch Manager that a GameObject is destroyed. You would have to add special code to every one of your GameObjects to tell me it's destroyed. If you do that, you should just remove the listeners in your OnDestroy() event instead of telling me to remove the listeners.

    You know when you add listeners. So, it's best that you remove the listeners based on how you setup your code.
     
  48. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Interesting. There is no callback event on destroy. Until I find a way to do it, I must do it manually.
    BTW, what happens if I don't remove the listener? If there many dangling listener (let say ~1000), will it hurt the perf? or harmless?

    I guess one of handling this is that we can remove the dangling listener on the first call that is not found. I think it's safe to assume that it's deleted. Yeah, there is little danger that SendMessage is called before AddListener but it's very unlikely if you add Listeners in Awake and SendMessages after Awake.
    If you want to make sure the Listener to stays, we can specify a flag when adding the Listener. This way, we can get away with not having to manage the dead Listeners.

    Sorry, I really try to avoid unnecessary boilerplating if possible.
     
  49. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Correct. Your GameObject will have OnDestroy() called. However, there's no callback to some other GameObject (like the Dispatch Manager) to tell them that your GameObject was destroyed.

    Since I use dictionaries, the performance hit will be minimal. However, memory would be wasted. Eventually it could become an issue.

    This doesn't work well for people using object pooling. The race condition could also become an issue.

    If you're adding the listener, just add the code to remove the listener where you need too. This allocate/release pattern is standard in programming... especially in memory management.
     
  50. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    I mentioned below but I'll take it back. It's the same situation regardless. You can't really call SendMessage when there is no Listener. The SendMessage will work correctly only after the Listener is added.

    I think my suggestion to remove the Listener upon nonexistence will work and it can help us not managing manually.

    I have to think what you said about pooling situation. If you are use pooling, how do you prevent the same Listener to add twice? If you are handing pooled object separately, we can do the same thing about removing it. Or since pooled objects are not destroyed but just dormant, the automatic removal system will not try to remove the Listener, therefore no need to anything.

    Please think about it and it will make the API much more convenient.

    Right now, I have to create Destroy() and add RemoveListener for all AddListener counter parts. Not fun if it can be avoided.

    Thanks.
     
    Tryz likes this.