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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

How to get unityevent listeners?

Discussion in 'Scripting' started by mahdiii, Jun 27, 2020.

  1. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    855
    Hello. I want to get all gameobjects with missing references in unity events (custom scripts, UIs, etc.)
    I use reflections. How can I get unityevent listeners?
    By using reflection, I iterate over all gameobjects and their components, then I find serialized UnityEvent fields.
    Now, I need to get missing listeners (methods), for example because of removing that component or changing method name.
     
  2. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    There is no way to directly get the functions that stopped listening.

    But whenever you listen to an event, you can store a reference to the object of that listener.
    Then do a check, something like this. You would need to pass a reference to the listener method, some method to reinstate, and the component.

    Code (CSharp):
    1. using system.linq;
    2.  
    3. class ListenerInfo
    4.  
    5. {
    6.     MethodInfo listener;
    7.     MethodInfo reInstator;
    8.     Component component;
    9. }
    10.  
    11. Lisct<ListenerInfo> listenerInfos
    12. UnityEvent e
    13.  
    14. Foo()
    15. {
    16.     list<string> currentEventListeners;
    17.     for(int i = 0; i < e.GetPersistentEventCount){
    18.         currentEventListeners.Add(e.GetPersistentMethodName(i));
    19.     }
    20.  
    21.     listenerInfos.where(x => !currentEventListeners.contains(.listener)).ToList().ForEach(x => {
    22.         //ListenerInfo with listener not in list
    23.         x.reInstator.Invoke(x.component); // Call the function on the listener to re-subscribe
    24.     });
    25. }
     
  3. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    Whenever you manually unsubscribe, just remove yourself from the list
     
  4. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,735
    I think OP is talking about at edit time, not runtime, to find broken event subscriptions from changing method names etc.
     
    Cyber-Dog likes this.
  5. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    Ahhh ok :)
     
  6. mahdiii

    mahdiii

    Joined:
    Oct 30, 2014
    Posts:
    855
    yes, at edit time, a tool to find missing references in Unityevents and UnityEvents<>
     
  7. Cyber-Dog

    Cyber-Dog

    Joined:
    Sep 12, 2018
    Posts:
    352
    I don't think that would work, because most of your code wont actually be "running"
    So if you assign a listener through code, it is not actually assigned until that line of code is run.

    If you wanting it to be done at editor time with (custom scripts, UIs, etc.). Then its a huge job. Despite the rest, for custom scripts; you would need to create an Editor script for every component you make. And handle the logging of info from there. And you could only track things assigned by Inspector, through code.

    Allot of work, might as well just get your method names right from the start.
     
  8. Flownity

    Flownity

    Joined:
    Sep 12, 2020
    Posts:
    2
    I had a similar problem today and since I found this post on top of google I would like to share my solution.
    This method checks if there is a method that matches the selected method on UnityEvent in the inspector.

    public void AssertHasNoBrokenListener(UnityEventBase evnt, string eventName)
    {
    for (int i = 0; i < evnt.GetPersistentEventCount(); i++)
    {
    Assert.That(evnt.GetPersistentTarget(i).GetType().GetMethod(evnt.GetPersistentMethodName(i), evnt.GetType().GenericTypeArguments) != null, eventName + " has broken listener");
    }
    }
     
    J_Kost likes this.