Search Unity

adding OnClick with a parameter to a button at runtime not working

Discussion in 'Scripting' started by steveh2112, Jan 18, 2020.

  1. steveh2112

    steveh2112

    Joined:
    Aug 30, 2015
    Posts:
    314
    i have the following code
    Code (CSharp):
    1.  
    2.     public void OnClickMaterialChooserDir(int idx)
    3.     {
    4.         Debug.Log("OnClickMaterialChooserDir "+idx);
    5.     }
    6.  
    7.     public void PopulateMaterialChooserPanel()
    8.     {
    9.         //Debug.Log("PopulateMaterialChooserPanel");
    10.  
    11.         string myPath = "Assets/Resources/Materials/";
    12.         DirectoryInfo matdir = new DirectoryInfo(myPath);
    13.  
    14.         DirectoryInfo[] dirInfo = matdir.GetDirectories();
    15.  
    16.         //FileInfo[] info = dir.GetFiles("*.*");
    17.         int i = 0;
    18.         foreach (DirectoryInfo dir in dirInfo)
    19.         {
    20.             //ItemGameObject is my prefab pointer that i previous made a public property
    21.             //and  assigned a prefab to it
    22.             DefaultControls.Resources TempResource = new DefaultControls.Resources();
    23.             GameObject buttonGO = DefaultControls.CreateButton(TempResource);
    24.             buttonGO.AddComponent<LayoutElement>();
    25.             Button dirButton = buttonGO.GetComponent<Button>();
    26.             dirButton.onClick.AddListener(() => { OnClickMaterialChooserDir(i); }); //AddListener(delegate { OnClickMaterialChooserDir(i); });
    27. Debug.Log("PopulateMaterialChooserPanel "+i);
    28.             i++;
    29.             Text text = dirButton.transform.GetChild(0).GetComponent<Text>();
    30.             text.text = dir.Name;
    31.             text.fontStyle = FontStyle.Bold;
    32.             text.fontSize = 16;
    33.  
    34.             dirButton.transform.SetParent(_MaterialChooserScrollViewContent, false);
    35.         }
    36.     }
    It creates buttons in a scrollview based on the directories in a resources folder, and it works, the buttons are created, the correct label text is set and i can click.
    but when i get the callback to OnClickMaterialChooserDir idx is always 3 (the number of directories in this case)
    i got the idea for the code from here
    https://answers.unity.com/questions/1288510/buttononclickaddlistener-how-to-pass-parameter-or.html
    i tried both the delegate method and the one you see here and both give the same result
    does anyone know what's wrong?
    thx
    PS, PopulateMaterialChooserPanel() is only called from Start

    i suspect the problem is the buttons are created at run time, not sure
     
    Last edited: Jan 18, 2020
  2. steveh2112

    steveh2112

    Joined:
    Aug 30, 2015
    Posts:
    314
    ok i found it, i think if i had done a 'new Int()' instead of 'i' it would have worked, anyhow this is want i really wanted and it works

    Code (CSharp):
    1.     public void OnClickMaterialChooserDir(string dir)
    2.     {
    3.         Debug.Log("OnClickMaterialChooserDir "+dir);
    4.         //PopulateMaterialChooserPanel(dir);
    5.     }
    6.  
    7.     public void PopulateMaterialChooserPanel(string baseDir)
    8.     {
    9.         //Debug.Log("PopulateMaterialChooserPanel");
    10.  
    11.         string myPath = "Assets/Resources/Materials/"+ baseDir;
    12.         DirectoryInfo matdir = new DirectoryInfo(myPath);
    13.  
    14.         DirectoryInfo[] dirInfo = matdir.GetDirectories();
    15.  
    16.         FileInfo[] fileInfo = matdir.GetFiles("*.mat");
    17.  
    18.         foreach (DirectoryInfo dir in dirInfo)
    19.         {
    20.             //ItemGameObject is my prefab pointer that i previous made a public property
    21.             //and  assigned a prefab to it
    22.             DefaultControls.Resources TempResource = new DefaultControls.Resources();
    23.             GameObject buttonGO = DefaultControls.CreateButton(TempResource);
    24.             buttonGO.AddComponent<LayoutElement>();
    25.             Button dirButton = buttonGO.GetComponent<Button>();
    26.             dirButton.onClick.AddListener(() => { OnClickMaterialChooserDir(dir.Name); }); //AddListener(delegate { OnClickMaterialChooserDir(i); });
    27.             Text text = dirButton.transform.GetChild(0).GetComponent<Text>();
    28.             text.text = dir.Name;
    29.             text.fontStyle = FontStyle.Bold;
    30.             text.fontSize = 16;
    31.  
    32.             dirButton.transform.SetParent(_MaterialChooserScrollViewContent, false);
    33.         }
    34.     }
     
  3. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @steveh2112

    I didn't read your code properly but:
    Code (CSharp):
    1. // AddListener(delegate { OnClickMaterialChooserDir(i);
    If you want to use this, that "i" must be a local variable in that loop for it to work... it is called C# closure I think.