Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved How do you handle multiple button addlistener?

Discussion in 'Scripting' started by hyperkvlt, May 2, 2022.

  1. hyperkvlt

    hyperkvlt

    Joined:
    Aug 16, 2020
    Posts:
    37
    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?

    Code (CSharp):
    1.         [SerializeField] private Button[] myButtons;
    2.  
    3.         private void Awake()
    4.         {
    5.             int i = 0;
    6.             foreach (Button btn in myButtons)
    7.             {
    8.                 btn.onClick.AddListener(() => { MyFunc(i); });
    9.  
    10.                 i++;
    11.             }
    12.         }
    13.  
    14.         private void MyFunc(int index)
    15.         {
    16.             Debug.Log($"index = {index}");
    17.         }
     
  2. hyperkvlt

    hyperkvlt

    Joined:
    Aug 16, 2020
    Posts:
    37
    Nevermind, I solved it.

    Code (CSharp):
    1.       [SerializeField] private Button[] myButtons;
    2.  
    3.         private void Awake()
    4.         {
    5.             int i = 0;
    6.             foreach (Button btn in myButtons)
    7.             {
    8.                 ListenerHandler(btn, i);
    9.  
    10.                 i++;
    11.             }
    12.         }
    13.  
    14.         private void ListenerHandler(Button btn, int index)
    15.         {
    16.             btn.onClick.AddListener(() => { MyFunc(index); });
    17.         }
    18.  
    19.         private void MyFunc(int index)
    20.         {
    21.             Debug.Log($"index = {index}");
    22.         }
     
    Bunny83 likes this.
  3. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    604
    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:

    Code (CSharp):
    1. int i = 0;
    2. foreach (Button btn in myButtons)
    3. {
    4.          int j = i;
    5.          btn.onClick.AddListener(() => { MyFunc(j); });
    6.          i++;
    7. }
     
    Bunny83 and hyperkvlt like this.
  4. hyperkvlt

    hyperkvlt

    Joined:
    Aug 16, 2020
    Posts:
    37
    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?
     
  5. karliss_coldwild

    karliss_coldwild

    Joined:
    Oct 1, 2020
    Posts:
    604
    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.
     
    Bunny83 likes this.