button.onClick.AddListener in for loop
I need to add button with onclick event but I cant
for (int i = 0; i < 10; i++)
{
var obj = new GameObject();
obj.AddComponent<Button>();
obj.GetComponent<Button>().onClick.AddListener(() => somefunc(i));
}
problem is after Start() ends, i is setting to null and when I click on button it raises ArgumentOutOfRangeException. How can I solve this problem?
Note: All code :
void Start () {
player = GlobalVariables.player;
for (int i = 0; i < player.items.Count; i++)
{
var obj = new GameObject();
obj.AddComponent<Image>();
Image image = obj.GetComponent<Image>();
image.sprite = Resources.Load <Sprite>(player.items[i].slug.ToString());
var wear = new GameObject();
wear.AddComponent<RectTransform>();
wear.AddComponent<Button>();
wear.AddComponent<Image>();
wear.GetComponent<Image>().sprite = Resources.Load<Sprite>("UISprite");
wear.GetComponent<RectTransform>().transform.localScale = new Vector3(0.1f, 0.1f, wear.GetComponent<RectTransform>().transform.localScale.z);
wear.GetComponent<Button>().onClick.AddListener(() => player.wearItem(player.items[i]));
wear.transform.SetParent(obj.transform);
obj.transform.SetParent(inventory);
}
}
Answer by Kaze47 · Aug 10, 2017 at 09:24 AM
I don't know why, but i have the same problem
obj.GetComponent<Button>().onClick.AddListener(() => somefunc(i));
try
int x = i;
obj.GetComponent<Button>().onClick.AddListener(() => somefunc(x));
Your "try" works perfect! Looks like it's a sort of buf from Unity who lose the scope of loop variable, it's crazy because x is a copy of i but works.
It's not a bug of Unity. It's called the closure problem, and it's a known behaviour in almost all the languages providing lambda expressions....
https://stackoverflow.com/questions/271440/captured-variable-in-a-loop-in-c-sharp
Answer by junedmmn · Dec 12, 2018 at 01:56 PM
It is due to the closures simply use a copy variable, and it's done.
for (int i = 0; i < 10; i++)
{
int copy = i;
var obj = new GameObject();
obj.AddComponent<Button>();
obj.GetComponent<Button>().onClick.AddListener(() => somefunc(copy));
}
Your answer
Follow this Question
Related Questions
OnClick() event script from a prefab 0 Answers
How can I start a Coroutine with the onClick of a button? 0 Answers
Detecting a button click 1 Answer
Script loads wrong information 0 Answers
Disable or hide GUI Buttons on one scene 2 Answers