Search Unity

Event System - Dispatcher

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

  1. helloworldgames

    helloworldgames

    Joined:
    Mar 16, 2017
    Posts:
    60
    @Tryz, what is this new feature? "Sync support files"
     
  2. TeagansDad

    TeagansDad

    Joined:
    Nov 17, 2012
    Posts:
    957
    There are a number of files that are distributed with all of the ootii assets (contained within the Framework_v1 subfolder, but not everything in there is included with every asset). Any time that one of those shared support files are updated, all of the assets which include that file need to be updated so that nothing gets overwritten when importing multiple assets.
     
    Tryz and helloworldgames like this.
  3. chrisk

    chrisk

    Joined:
    Jan 23, 2009
    Posts:
    704
    Hi, I have one critical issue using the dispatcher.
    The dispatcher is based on the name but many objects can have the same name.
    I think this is rather a big limitation.
    Can you please add support based on the actual object reference?
    Thanks.
     
    Duffer123 likes this.
  4. bugscuffle

    bugscuffle

    Joined:
    Dec 8, 2015
    Posts:
    73
    I keep trying to get the Web Demo.. the web demo won't run in ANY browser these days.. they've all dropped it.
     
  5. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    I just tested and Internet Explorer is working fine.

     
  6. lolaswift

    lolaswift

    Joined:
    Jan 10, 2019
    Posts:
    151
    IE is old :).It doesn't work with Edge, firefox and chrome.
     
  7. DavidLe360

    DavidLe360

    Joined:
    Dec 24, 2018
    Posts:
    127
    Hi, Visual Studio don't find reference for 'MessageDispatcher':
    upload_2020-5-7_17-21-46.png
     

    Attached Files:

  8. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    It's in the "com.ootii.Messages" namespace that on line 3 and I'm not seeing any issues here. That hasn't changed in a long time.

    Make sure you don't have two classes in your project named "MessageDispatcher". Please check other assets you've imported and make sure they are using namespaces.
     
    DavidLe360 likes this.
  9. craigjwhitmore

    craigjwhitmore

    Joined:
    Apr 15, 2018
    Posts:
    135
    Is there a version of this that uses bitmasks for filtering instead of using compare strings. Bitmasks a massively faster and will not consume nearly as much cpu as comparing strings? Each character of a string is comparing 64bits of data, which, I don't think is native binary, where as a bitmask does a single native binary compare of 32 bits.
     
  10. Tryz

    Tryz

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

    Unfortunately there isn't. I address this in the documentation:

    A word on string types

    Some developers hate strings and prefer to use hashed values or simple int values. While it’s true, there is a performance benefit to doing this, we’re typically talking tiny fractions of a millisecond. As long as we don’t manipulate the strings, there’s little to no impact on the garbage collector as well.

    Since the majority of users on the Asset Store aren’t hard-core programmers, I decided to go with strings for readability. Even with this approach, I’m finding that the Event System – Dispatcher is 30% to 100% faster than the standard Unity event system.


    You are right about ints being faster, but it's so small that I felt using strings were more readable and easier to debug. The performance-micro-hit was worth it.
     
  11. DavidLe360

    DavidLe360

    Joined:
    Dec 24, 2018
    Posts:
    127
    How to make it works with 'enter play mode'?:
    upload_2020-11-21_11-40-25.png
     
  12. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Replace MessageDispatcher.cs lines 40-45 with this code:

    Code (CSharp):
    1.         /// <summary>
    2.         /// Create the MessengerStub at startup and tie it into the Unity update path
    3.         /// </summary>
    4.         private static MessageDispatcherStub sStub = null;
    5.  
    6.         /// <summary>
    7.         /// Static constructor
    8.         /// </summary>
    9.         static MessageDispatcher()
    10.         {
    11.             Initialize();
    12.         }
    13.  
    14.         /// <summary>
    15.         /// This function is simply to allow us to use Unity 2019's "Enter Play Mode" settings with Reload Domain disabled.
    16.         /// </summary>
    17. #if UNITY_EDITOR && !UNITY_5 && !UNITY_2017 && !UNITY_2018
    18.     [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    19. #endif
    20.         static void Initialize()
    21.         {
    22.             sStub = (new GameObject("MessageDispatcherStub")).AddComponent<MessageDispatcherStub>();
    23.         }
    This is based on Unity's Domain Reloading documentation.

    Since this feature from Unity is "experimental", be prepared that it could go away. I'll support it if it doesn't cause issues with Unity 2020+.
     
    Deleted User and DavidLe360 like this.
  13. unlikelysurvival

    unlikelysurvival

    Joined:
    Aug 17, 2017
    Posts:
    5
    It took me less than an hour to convert it, you could easily do the same. I wasnt worried about speed because Tryz is right it really doesnt make a difference these days and for most projects. Compared to most Unity projects you'd be looking at an edge case. When you have multiple developers working on a project though I'd rather not "hope" a string doesnt have a typo at some point, I'd rather it all be tied to enums.

    Obviously it's still possible someone changes it to something completely different but it eliminates alot of the risk. We have multiple solutions for different parts of the project, we've setup a "shared" folder amongst all of them so anytime I add something into lets say PlayerEvents enum it's accessible in all the other solutions instantly.

    Probably just personal preference but feels better this way to me :)
     
    Tryz likes this.
  14. FiveFingerStudios

    FiveFingerStudios

    Joined:
    Apr 22, 2016
    Posts:
    510
    Does this asset use list or dictionaries to store the events?

    I'm asking because I'm looking for a solution for a particular Monobehavior that I need to turn on and off a lot. My current solution uses dictionaries and causes a lot of GC when its disabled...which I want to get rid of.
     
  15. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    It does use dictionaries, but I did a lot of testing (a while back) to ensure it wasn't needing the GC. For example, the support structures that hold the GameObjects are pooled and I move through the dictionary in a way that severely limits garbage.

    I can't promise there will be 0, but it should almost 0.
     
  16. yanyoumo_unity

    yanyoumo_unity

    Joined:
    Apr 30, 2020
    Posts:
    15
    Hi there, I've countered a situation, I can't be sure it's a bug or I missed somehting. In one word, RemoveListener seemed not workding.

    Of course I'll elaborate, this is my code,
    Code (CSharp):
    1. public class foo{
    2.     protected bar controller;
    3.     void Awake{
    4.         bar=new controller();//I added listener here.
    5.     }
    6. }
    7.  
    8. public class foo1:foo{
    9.     void Awake(){
    10.         base.Awake();
    11.         bar.clean();//I remove listener here.
    12.         bar=null;
    13.         bar=new controller();
    14.     }
    15. }
    However, the controller is still being triggered twice, so, it appears to me the remove attempt failed.
    I added by:
    Code (CSharp):
    1. //In constructor
    2. MessageDispatcher.AddListener("TestEvent", TestEventHandler);
    I removed by:
    Code (CSharp):
    1. //in a void function (clean)
    2. MessageDispatcher.RemoveListener("TestEvent", TestEventHandler);
    so, any idea?
     
  17. mohi86

    mohi86

    Joined:
    Oct 23, 2020
    Posts:
    2

    I'm having the same issue! Did you find a solution for this?
     
  18. Tryz

    Tryz

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

    I think what's happening is that the AddListener(...) and RemoveListener(...) are being cached. So, the AddListener(...) isn't really creating a listener when you think it is... so nothing is removed. I talk about this in the User's Guide (under Caching Listeners).

    Some people were trying to remove listeners while responding to the listener. This is a problem because you can't destroy the thing you're in.

    So, AddListener(...) and RemoveListener(...) have an argument for "rImmediate". By default it's "false" and that means add or remove won't happen until the end of the frame. If you want to add or remove immediately, you need to call the function with "true" as the "rImmediate" value.
     
  19. Tryz

    Tryz

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

    I haven't been able to reproduce this, but I'll add some protection in that may help.

    In the MessageDispatcher.cs, replace the current Initialize() function with the following:

    Code (CSharp):
    1.         static void Initialize()
    2.         {
    3.             if (sStub == null)
    4.             {
    5.                 sStub = Component.FindObjectOfType<MessageDispatcherStub>();
    6.                 if (sStub == null) { sStub = (new GameObject("MessageDispatcherStub")).AddComponent<MessageDispatcherStub>(); }
    7.             }
    8.         }
    That will do a double check for an existing stub.
     
  20. FargleBargle

    FargleBargle

    Joined:
    Oct 15, 2011
    Posts:
    774
    Is there something wrong with the assembly definitions? Adding the "using com.ootii.Messages;" line to my scripts generates an error saying that Messages doesn't exist in the com.ootii namespace:

    MD_Error1.png

    If I move my script to one of the MD demo scene folders, the namespace error goes away, but VB still highlights any calls to MessageDispatcher - both in my scripts and the demo scripts:

    MD_Error2.png

    I saw that @DavidLe360 reported something similar above, but at least his "using" line seemed unaffected. Also, if this is caused by a conflict with another MessageDispatcher asset - which I can't find anywhere in my test project - why does the error say the name doesn't exist? Shouldn't it say the name already exists somewhere else? This may be nothing, since even with the namespace and MessageDispatcher errors showing in VB, the scripts still work fine in game - even after moving them back to my own scripts folder from the Ootii demo folder. It's just a little disconcerting that VB isn't signing off on them. Since I'm still trying to figure out how this asset works, these kind of shenanigans only add to my confusion. :(
     
    Last edited: Oct 3, 2021
  21. Dusty777

    Dusty777

    Joined:
    Jul 23, 2016
    Posts:
    9
    Hey I could use some help

    I can't get listener owner filters to work.
    Perhaps I could request a demo be added showing it in use??

    See below. I'm sure I'm missing something.
    I'm trying to follow this signature from the documentation:

    AddListener(UnityEngine.Object rOwner, string rMessageType, MessageHandler rHandler)

    The script:

    public GameObject onlyOneIListenFor;

    void Start()
    {
    MessageDispatcher.AddListener(onlyOneIListenFor, "Color", ColorHandler);
    }
     
  22. Tryz

    Tryz

    Joined:
    Apr 22, 2013
    Posts:
    3,402
    Hi. When using the object (name) as a filter for AddListener(...), you'll need to send the message using the signature with the object as the recipient. Here's an example:


    Code (CSharp):
    1. using UnityEngine;
    2. using com.ootii.Messages;
    3.  
    4. public class Sample2 : MonoBehaviour
    5. {
    6.     public GameObject onlyOneIListenFor; // Sphere
    7.  
    8.     public GameObject ObjectIDoNotListenFor; // Cube
    9.  
    10.     private void Start()
    11.     {
    12.         // When adding a listener with an object, we store the name as the "filter".
    13.         MessageDispatcher.AddListener(onlyOneIListenFor, "Color", ColorHandler);      
    14.     }
    15.  
    16.     private void OnGUI()
    17.     {
    18.         if (GUI.Button(new Rect(10f, 10f, 100f, 20f), "Fire Event Sphere"))
    19.         {
    20.             // When sending a message, we can send it to that object like this.
    21.             MessageDispatcher.SendMessage(this, onlyOneIListenFor, "Color", Color.red, 0f);
    22.         }
    23.  
    24.         if (GUI.Button(new Rect(10f, 35f, 100f, 20f), "Fire Event Cube"))
    25.         {
    26.             // Here's a message for a different object. It won't go through since the name filter doesn't match.
    27.             MessageDispatcher.SendMessage(this, ObjectIDoNotListenFor, "Color", Color.blue, 0f);
    28.         }
    29.     }
    30.  
    31.     public void ColorHandler(IMessage rMessage)
    32.     {
    33.         Color lColor = (Color)rMessage.Data;
    34.         Debug.Log("Here color:" + lColor.ToString());
    35.     }
    36. }
    37.  
    On line 21, I'm sending to the correct object and I get the message. On line 27, I'm sending to a different object and the message is ignored.

    Basically, the object name becomes a filter. We need to use the specific SendMessage(...) so the recipient's name is grabbed.

    I hope that helps,
    Tim
     
    FargleBargle likes this.
  23. Deleted User

    Deleted User

    Guest

    I always end up having MessageDispatcherStub game object on my scene whenever I open Unity. Using Editor fast reload feature. It's quite annoying now; is there anything we can do ? I've tried all the above none of them works. Thanks !
     
  24. Deleted User

    Deleted User

    Guest

    @Tryz My question isn't worth a reply ? It's a bit rude.
     
  25. hopeful

    hopeful

    Joined:
    Nov 20, 2013
    Posts:
    5,684
    Try a direct message to this asset's support email. You'll notice his last reply in this forum was more than a year ago.