Search Unity

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.