what is wrong with my for loop?
Hi I'm new to unity3D and really enjoying creating what I want to make. But while making the friend request accept/refuse system, I'm struggling with with a for loop which adds listeners to UI Buttons. During runtime, every Buttons are having the last listener. for example, if for loop conditions were (int i=0; i<5; i++), and when I debug a listener attached to the button, the button always have fifth button listener that isn't in the condition. Here is my script, and sorry for my short English.
//start from here
void Awake ()
{
StartCoroutine (CheckingRequest ());
username.text = PlayerPrefs.GetString("username");
}
//gets username from Mysql Database, and split that for buttons
IEnumerator CheckingRequest ()
{
WWWForm form = new WWWForm ();
form.AddField ("userNamePost", PlayerPrefs.GetString("username"));
WWW www = new WWW (CheckingRequestUrl, form);
yield return www;
Debug.Log (www.text);
requestNum = www.text.Split ('|').Length - 1;
Debug.Log (requestNum);
testString = www.text;
//here is problem area
for (int i = 0; i < requestNum; i++)
{
friendRequest [i].text = www.text.Split ('|') [i];
Debug.Log (i);
acceptButton [i].onClick.AddListener (() => AcceptRequestWrapper (i));
}
}
IEnumerator AcceptRequest (string friendRequesting)
{
WWWForm form = new WWWForm ();
form.AddField ("userName", PlayerPrefs.GetString("username"));
form.AddField ("actionUser", friendRequesting);
WWW www = new WWW (AcceptRequestUrl, form);
yield return www;
Debug.Log (www.text);
}
public void AcceptRequestWrapper (int e)
{
Debug.Log (e);
StartCoroutine (AcceptRequest (friendRequest[e].text));
Debug.Log (friendRequest [e].text);
Debug.Log ("Button Clicked");
}
Answer by NoseKills · Oct 18, 2016 at 04:25 PM
for (int i = 0; i < requestNum; i++) {
acceptButton [i].onClick.AddListener (() => AcceptRequestWrapper (i));
}
When using a lambda like this, the actual variable (`i`) gets wrapped into the closure, not the value of it.
In other words, when you finally press the button and AcceptRequestWrapper gets called, the loop has already finished and the value of i
is indeed what it is when the loop finishes.
You should be able to easily avoid this by giving the lambda a new int you dont change in the loop.
for (int i = 0; i < requestNum; i++) {
var tempI = i;
acceptButton [i].onClick.AddListener (() => AcceptRequestWrapper (tempI));
}
Answer by Dave29483 · Oct 17, 2016 at 07:44 AM
In the example you provided
(int i=0; i<5; i++)
This loop will run 5 times, not four. If your loop started at 1, it would run 4 times.
The zero index counts as a loop too.
Thank you for a fast replying. Then, how can I abbreviate that process? Is there any appropriate way to shorten the line? Should I write all codes regardless of the length?
Answer by Zodiarc · Oct 18, 2016 at 10:51 AM
Use a foreach loop then you won't need to deal with array sizes (pseudocode):
foreach(FriendRequest friendRequest in friendRequests) {
// do your stuff here
}