Let me give you a simplified version of my script:
using UnityEngine.UI;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Whatever : MonoBehaviour {
//Pretend this is a list with 5 or so elements
List<GameObject>() myGos = new List<GameObject>();
void Start() {
for(int i = 0; i < myGos.Count; i++) {
string nameThing= i.ToString();
myGos*.GetComponent<Button>().onClick.AddListener(() => DebugNumber(nameThing));*
}
}
public void DebugNumber(string num) {
Debug.Log(num);
}
}
Now don’t look for little errors here because I just typed up a quick example of what I’m wanting. Okay, so let’s say that I now have 4 or so buttons, and each one should have a listener in onClick() so that once I click one, it will print a number, whichever one was assigned i
in the for loop above. So, if I click all the buttons, I should get a mix of numbers 1-4. Do I? No. I am getting 4 for All of Them.
So what’s the problem?
If I print nameThing
in my for loop, I will get the 1-4 I want.
If I print nameTHing
when DebugNumber
is called when I click a button, I get ONLY 4.
Why? And how can I fix it?
Thank you.
Edit:
If this looks like it’s working for you, try replacing the DebugNumber(nameTHing());
line with DebugNumber(i.ToString()));
, then it won’t work.
WHY? WHy do I need to set i.ToString() Before I add the listener?
Well, since this doesn’t seem to be your actual code the question is quite pointless. The behaviour you’re describing would appear when your closure is capturing the for variable “i”.
In your case you create a local string variable that get captured by the closure so that problem shouldn’t occur.
So for example if you would do this:
void Start() {
for(int i = 0; i < myGos.Count; i++) {
myGos*.GetComponent<Button>().onClick.AddListener(() => DebugNumber(i.ToString()));*
}
}
In this case when you have 5 buttons in the list you will always see the number “5” since that’s the last number i will contain. All closures have captured the same variable “i” and therefore will see the last value when executed.
However your code uses a local string variable inside the for loop. This will create a “new” variable each iteration and each closure will capture an individual variable. It doesn’t have to be a string variable. This does work as well:
void Start() {
for(int i = 0; i < myGos.Count; i++) {
int localVar = i;
myGos*.GetComponent().onClick.AddListener(() => DebugNumber(localVar.ToString()));*
}
}
So considering your code in your question we can’t reproduce that problem.
> Now don’t look for little errors here …
Well, what do you consider little errors? It doesn’t really matter how “little” an error is if it causes the problem…
I have since discovered what my issue is, that because I have a simplified code in my question, you guys were not able to detect any significant problems.
In my code that was not provided, I have used the simplified version in a coroutine, and after moving the stuff between the for loop to a new function and passing the index, I was able to achieve the result I was wanting without any problems.
Again, thank you for everyone’s response.