- Home /
Onclick.Addlistener issues in for statement. (also network related).
Hi, I'm working on assigning things to buttons as seen below. Currently each button I'm trying to assign a listener to is called ServerNamePrefab 0, ServerNamePrefab 1, 2 3 etc.(though they are not actual prefabs but rather duplicates of the original).
In anycase, they're currently set up in a UI improvised list I've made, and the code can be seen below.
UnityEngine.UI.Text[] GamNam = new UnityEngine.UI.Text[hostData.Length]; //sets array length of text component GamNam.
UnityEngine.UI.Button[] GamBut = new UnityEngine.UI.Button[hostData.Length];//sets array length of button component GamBut.
GameObject[] ServerName = new GameObject[hostData.Length];
HostData curhost;
for (int i = 0; i < hostData.Length; i++){
string j = i.ToString();
//UnityEngine.UI.Text[] GamNam = new UnityEngine.UI.Text[hostData.Length]; //sets array length of text component GamNam.
//UnityEngine.UI.Button[] GamBut = new UnityEngine.UI.Button[hostData.Length];//sets array length of button component GamBut.
//GameObject[] ServerName = new GameObject[hostData.Length];
//HostData curhost;
//finds GameObject of name "ServerNamePrefab i"(though it isnt really a prefab)
ServerName[i] = GameObject.Find ("ServerNamePrefab " + j);
ServerName[i].SetActive(true);
//finds button text to set gameroomname.
GamNam[i] = ServerName[i].GetComponentInChildren<UnityEngine.UI.Text>();
GamNam[i].text = hostData[i].gameName;
Debug.Log (hostData[i].gameName);
//debugs the correct name for that hostData.
curhost = hostData[i];
GamBut[i] = ServerName[i].GetComponent<UnityEngine.UI.Button>(); // is a button component of ServerName GameObject.
GamBut[i].onClick.AddListener(() => ConnectToHost(curhost));//Adds listener of button on ServerName Button i.
//as GamBut[i] is component oon ServerName GameObject i.
They're located inside of an IEnumerator which is used to refresh the server list. In anycase, I've tried many things but for some reason the addlistener no matter which button I press, always connects to the last hostData, dispite attempting to assign one on each button i, for that host i's host data.
In anycase, hopefully someone here can explain what's happening. Additionally here is the ConnectToHost function which is being called by the addlistener.
public void ConnectToHost(HostData SelHost){
if (SelHost != null) {
Network.Connect (SelHost);
Debug.Log("connecting to " + SelHost.gameName);
}
}
as said, the parameter being sent on all buttons ends up being hostData[hostData.Length - 1] (or the last hostData array cell.) This bug has kept me busy all day, hopefully someone can shed some light on what I'm doing wrong.
Answer by Mmmpies · Feb 26, 2015 at 11:32 AM
I know it sounds like madness but when you set a lambda or delegate in a loop you have to create a copy of the object to pass that a copied value of i. Answered a very similar question about this the other day:
Like I said it's madness, to my mind anyway but it works.
So essentially I should make a function, just to handle passing that listener to the ConnectToHost function for that button ServerName[i]? I guess I'm a little confused because of the way its occuring, what I'm trying to do, and how to relate it to that particular response... How would I go about creating this second function to pass host data, so that when I go back and click a button it knows which has been clicked?
Not got unity at the mo so I'll get back to you in about 45 $$anonymous$$s.
Awesome, and thanks a million btw. Also no rush, I've implemented a workaround for now thats doing the trick.
Not touched on Networking at all but where you get the button try setting a tempButton and tempInt to fool the lambda/delegate fuctionality:
GamBut[i] = ServerName[i].GetComponent<UnityEngine.UI.Button>();
Button tempButton = GameBut[i];
Int tempInt = i;
tempButton[tempTemp].onClick.AddListener(() = ConnectToHost(curHost));
I think it's just the way Lambdas and Delegates are setup to function, it's like they add the onClick but save adding the i loop value until the last loop. There must be a reason for it but whenever anyone's told me it's expected functionality I say "Oh that's interesting do you know why?" and that's the last I hear from them!
Give that a shot and see if it fixes it.
Oh you'll need
using UnityEngine.UI;
At the top for "Button tempButton = GamBut[i];" to know what Button is.
Eh I've just tried that still seems to have the same problem. I'm going to just go ahead and use the workaround.
Your answer
Follow this Question
Related Questions
List of Buttons: Adding a listener passes Last element? 2 Answers
[Bug?] int parameter on dynamically added onClick-Event is wrong 1 Answer
How to make it so only a certain section of a button will work on click 1 Answer
How to ADD one Buttons.onClick events to another Buttons.onClick? 1 Answer
Problem with touch and ui button 1 Answer