AddListener confusion?

I’m testing the AddListener method and it seems to be broken…

I made a simple button and added this script to it

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class AddListener : MonoBehaviour {

    void Start () {
        GetComponent<Button> ().onClick.AddListener (() => SomeFunction());
    }

    public void SomeFunction(){
        Debug.Log ("clicked");
    }
       
}

I even tried

 GetComponent<Button> ().onClick.AddListener (SomeFunction);

Do you get any errors?

This should work technically. As long as AddListener script is attached to the same GameObject as the Button.

no… sigh.

Edit:

This is so stressful. So the button method WAS added, but it just didn’t show in the inspector…

THIS WHOLE DAMN TIME

I didn’t even think to test the button, but technically it should have shown in the inspector button component that the method was added

1 Like

So I just tested your exact script, to make sure maybe there wasn’t some name collision (because the script is called AddListener after all). But no, it works just fine.

Make sure in your scene you have:

  1. a Button, it has to be a child of a Canvas
  2. an EventSystem exists in the scene, there must be one for interaction with the button to work
  3. the AddListener script is on the same GameObject as the Button script
  4. the Button and AddListener scripts are enabled
1 Like

This is by design. The inspector can only show persistent listeners, which are listeners that unity is able to serialize. Unity is only able to safely serialize public method of components. Listeners added at runtime could be methods of any type. They could be anonymous types, lambdas, external method calls… who knows.

4 Likes

I know it works now, I just thought it didn’t because it didn’t show in the inspector.
I never even clicked the button to test it x.x

1 Like

nono. The onclick event drawer shown in the inspector can only show the persistent listeners. Runtime listeners are actually added to a separate list that’s not exposed to the inspector. Then when an invoke comes along unity merges the persistent and runtime lists into a single invoke list and iterates that list to invoke calls.

I guess it could show the runtime bindings if it really wanted to, but it doesn’t. I even have my own WoofEvent class thats pretty similar to UnityEvent (with several added features), and even I feel that drawing the runtime listeners could be a bad idea. if you think about some events could have hundreds of listeners added in a blink of an eye, and then removed in the next blink. as a human reader it’d be next to impossible to keep up with the inspector and it’d likely resize like crazy, making using the inspector frustrating. Another reason is how to draw some of them. in the first example you passed in an anonymous function. a function with no name, and not directly belonging to the object that created it. not a lot of info would be available to show in the inspector.

The best I could think of would be to not draw each individual run-time listener. and instead draw a label that reports a count of runtime listeners. (hmm… I actually might do that for my Woof events, one extra feature)

1 Like

I know this is a selfish plug but I managed to add that feature to my Woof Events and I’d like to post a sneak peek here.

My events can now show a count of how many runtime listeners are attached to the object, the real work was writing the reflection call to traverse into array types for a serialized property.

WoofTools WoofEvents Editor example

As you can see the Vector3 Event has 5 runtime listeners attached while the Vector2 and Vector4 events don’t