- Home /
Problem with onClick.AddListener
So I'm making a store and using a for loop to go through all the guns that are available for purchase in an array called purGuns and creating a ui panel and button for each one. I'm doing button.onClick.AddListener(delegate { buyGun (thisStat.buyCost,i); }); in the loop but it seems like instead of putting in i as the paremeter, it's actually inputting purGuns.length which doesn't really make sense but I can't find the bug in the code quite yet. Here are the methods I'm using (and it's pretty rough, sorry):
void loadPurStore(){
GameObject.FindWithTag ("purContent").GetComponent<RectTransform> ().sizeDelta = new Vector2 (0, purGuns.Length * 95 + 5);
for (int i = 0; i < purGuns.Length; i++) {
clone = (GameObject)Instantiate (templatePurch,GameObject.FindWithTag("purContent").transform);
clone.GetComponent<RectTransform> ().localPosition = new Vector2 (-15, -50 - (95 * i) );
uiStats thisStat = purGuns [i].GetComponent<uiStats> ();
clone.transform.GetChild (1).GetComponent<Image> ().sprite = thisStat.gunIcon;
clone.transform.GetChild (3).GetComponent<Text> ().text = thisStat.gunName;
clone.transform.GetChild (2).GetChild (0).GetComponent<Text> ().text = "BUY\n" + thisStat.buyCost.ToString ();
clone.transform.GetChild(2).GetComponent<Button>().onClick.AddListener(delegate {
buyGun (thisStat.buyCost,i);
});
Debug.Log (i);
}
}
void buyGun(int cost, int ind){
Debug.Log (ind);
}
then what ends up happening is the Debug.Log(i) in the loadPurStore() does what I'd expect, when but I click the button, the Debug.Log in the other method will just log what seems to be the length of the public array purGuns. Also there's obviously more to buyGun, like some if statements and then clone = (GameObject)Instantiate (purGuns [ind], GameObject.FindGameObjectWithTag ("handR").transform); which is where i get the error that the array index is out of range.
Answer by Retrogue1 · Jul 26, 2017 at 03:01 PM
I just ran into this problem, all I had to do to fix it was to use a new variable in for the delegate instead of i.
Ex.
int id = i;
clone.transform.GetChild(2).GetComponent<Button>().onClick.AddListener(delegate {
buyGun (thisStat.buyCost,id);
});
This is because when onClick is called, the delegate gets the current value of i rather than the value when it was assigned. In the code, the value of id
doesn't change, it only creates new id
's with different values.
Yup. That's what happens and using a temp variable in the delegate is the way to go.
Ah ok cool, I'll edit my answer to be more confident then :P