I have the following code, but when I try to open a level, it always tries to open level 25, which does not exist! Thanks in advance!,

void Start () {
GetButtons ();
LevelNaming ();
}

private void GetButtons(){
		LevelButtons = LevelMenuContent.GetComponentsInChildren<Button> ();
	}

	private void LevelNaming(){
		for (int i = 0; i < LevelButtons.Length; i++) {
			LevelName = LevelButtons [(i)].GetComponentInChildren<TextMeshProUGUI> ();
			LevelName.text = (i + 1).ToString ();

			//
			//Onclick Listner
			//

			LevelButtons *.onClick.AddListener (() => DoTaskOnClick (i + 1));*
  •  }*
    
  • }*

  • private void DoTaskOnClick(int ClickedButtonIndex){*

  •  SceneManager.LoadScene(ClickedButtonIndex);*
    
  • }*
    private void LevelNaming(){

  •  for (int i = 0; i < LevelButtons.Length; i++) {*
    
  •  	LevelName = LevelButtons [(i)].GetComponentInChildren<TextMeshProUGUI> ();*
    
  •  	LevelName.text = (i + 1).ToString ();*
    
  •  	//*
    
  •  	//Onclick Listner*
    
  •  	//*
    

_ LevelButtons .onClick.AddListener (() => DoTaskOnClick (i + 1));_
* }*
* }*

* private void DoTaskOnClick(int ClickedButtonIndex){*
* SceneManager.LoadScene(ClickedButtonIndex);*
* }*

So I learned something new!

Looks like the issue you are seeing is a nuance of how C# and closures behave together. Now I am no C# expect but basically the actual value of i that is passed into DoTaskOnClick (i + 1) isn’t evaluated until the on click function gets called. At that point the loop is done and i has reached LevelButtons.Length so it is always sending 25 back.

From what I am reading you can get around this by declaring a local variable in the body of the for loop.

         for (int i = 0; i < LevelButtons.Length; i++) {
             int index = i;
             LevelName = LevelButtons [(i)].GetComponentInChildren<TextMeshProUGUI> ();
             LevelName.text = (index + 1).ToString ();
 
             //
             //Onclick Listner
             //
 
             LevelButtons [index].onClick.AddListener (() => DoTaskOnClick (index + 1));
         }

This will effectively create a ‘new’ variable for each one of the click handlers. Hopefully that explanation isn’t totally incorrect! I’m sure someone with more knowledge on the subject can correct me if I missed something.

For reference I ran into this stack overflow article which explains what is going on in more detail. closures - Captured variable in a loop in C# - Stack Overflow