How do you handle multiple button addlistener?

How do you exactcly handle add listener of multiple button on script?

I tried the following method but it always give me index 3. How do you get another index value here?

        [SerializeField] private Button[] myButtons;

        private void Awake()
        {
            int i = 0;
            foreach (Button btn in myButtons)
            {
                btn.onClick.AddListener(() => { MyFunc(i); });

                i++;
            }
        }

        private void MyFunc(int index)
        {
            Debug.Log($"index = {index}");
        }

Nevermind, I solved it.

      [SerializeField] private Button[] myButtons;

        private void Awake()
        {
            int i = 0;
            foreach (Button btn in myButtons)
            {
                ListenerHandler(btn, i);

                i++;
            }
        }

        private void ListenerHandler(Button btn, int index)
        {
            btn.onClick.AddListener(() => { MyFunc(index); });
        }

        private void MyFunc(int index)
        {
            Debug.Log($"index = {index}");
        }
1 Like

That’s one of the oddities how lambda variable captures work in C#. All the handlers you register refer to the same variable i even though it’s a local variable and normally wouldn’t exist after Awake is done exucuting. It would probably also work without introducing additional function if you did something like this:

int i = 0;
foreach (Button btn in myButtons)
{
         int j = i;
         btn.onClick.AddListener(() => { MyFunc(j); });
         i++;
}
3 Likes

Thanks, for the tips!

It’s good to know I am not the only one who finds it strange. So, it’s a commond oddity with C#, huh?

It is not unique to C# there are other programming languages using similar approach. It has it’s uses typically involving modification of captured variable. If I remember correctly javascript, python and swift behave similarly. Java forces captured variables to be final thus preventing such error. C++ and Rust allows you to choose if you want to capture the value or reference and makes you being a bit more explicit with it.

1 Like