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
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

onClick.AddListener() didn't work as expected.

Discussion in 'Scripting' started by Bodin, Dec 29, 2019.

  1. Bodin

    Bodin

    Joined:
    Apr 19, 2017
    Posts:
    37
    Hi,

    I have a problem with the script below.
    it's simple function to assign Listerner with parameter to a list of button.

    Code (CSharp):
    1. void SetupButton()
    2. {
    3.     for (int i = 0; i < ButtonList.Count; i++)
    4.     {
    5.         ButtonList[i].onClick.AddListener(() => OnButton(i));
    6.     }
    7. }
    8.  
    9. void OnButton(int i)
    10. {
    11.     Debug.Log("Click on : " + i);
    12. }
    I have 5 buttons in the list. it should show the number 0, 1, 2, 3, 4 when clicking on each button.
    but after run this code, no matter what button was clicked, it always return "Click on : 5"
    it seem to use the last value of i to assign to all button's parameter.

    but if I did the hard code for each button like this
    Code (CSharp):
    1. ButtonList[0].onClick.AddListener(() => OnButton(0));
    2. ButtonList[1].onClick.AddListener(() => OnButton(1));
    3. ButtonList[2].onClick.AddListener(() => OnButton(2));
    4. ButtonList[3].onClick.AddListener(() => OnButton(3));
    5. ButtonList[4].onClick.AddListener(() => OnButton(4));
    6.  
    now it's working fine as expected.

    Could someone please tell me why I can't use the for-loop to assign parameter to onClick.AddListener() method?

    Thanks in advance & best regards,
    Bodin
     
  2. Kamilche_

    Kamilche_

    Joined:
    Jan 11, 2015
    Posts:
    75
    Replace line 5 with these two lines:

    Code (CSharp):
    1.             int j = i;
    2.             ButtonList[i].onClick.AddListener(() => { OnButton(j); });
    3.  
    It's called 'closure', google 'c# unity closure' and you'll find lots of tutorials.
     
  3. Bodin

    Bodin

    Joined:
    Apr 19, 2017
    Posts:
    37
    Hi Kamilche_,

    thank you very much! I will try that.
     
  4. Bodin

    Bodin

    Joined:
    Apr 19, 2017
    Posts:
    37

    That's work! thank you very much.
    actually what I done is add this line
    Code (CSharp):
    1. int j = i;
    and used j instead of i for the next line.
     
    Kiwasi likes this.