Wait for onClick in a coroutine,

Hi everyone, I am new to Unity so this might have a straightforward answer. I am working on this dialogue box and want to display the next dialogue when the user clicks on the next button. Currently, it seems to fly through all dialogues just by one click. Here is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameController : MonoBehaviour {

	public Text gameText;
	public Button panelButton;

	private int instructions = 2;
	private int displayMessage = 0;

	// Use this for initialization
	void Start () {
		gameText.text = "Hi, Welcome to the Game!";
	}

	void InstructionMessages (int messageNumber) {
		switch (messageNumber) {
			case 0:
				gameText.text = "Instruction 0!";
				displayMessage++;
			        Debug.Log ("Case 0");
				break;
			case 1:
				gameText.text = "Instruction 1!";
				displayMessage++;
			        Debug.Log ("Case 1");
				break;
			case 2:
				gameText.text = "Instruction 2! Shouldn't come here though.";
				displayMessage++;
			        Debug.Log ("Case 2");
				break;
			case 3:
				gameText.text = "Just an extra Instruction for now that shouldn't be accessed.";
				displayMessage++;
			        Debug.Log ("Case 3");
				break;
		}
	}
	
	// Update is called once per frame
	void Update () {
		if (displayMessage < instructions) {
			StartCoroutine ("DialogueStart");
		}
	}

	IEnumerator DialogueStart() {
		Button instructionNextBtn = panelButton.GetComponent<Button> ();
		while (displayMessage < instructions) {
			instructionNextBtn.onClick.AddListener (delegate {
				InstructionMessages (displayMessage);
			});
			yield return null;
		}
		instructionNextBtn.gameObject.SetActive (false);
	}
}

As it stands now, I see the dialogue in Case 3 and the button disappears just after one click while ideally I would like to see “Instruction 0” outputted with one click.

Thanks
,

You register a new callback every frame. You should register it once at the start:

instructionNextBtn.onClick.AddListener (delegate {
    InstructionMessages (displayMessage);
});
while (displayMessage < instructions) {
    yield return null;
}

Note that when you want to reuse that coroutine several times you may want to clear the listeners before you add the new one.

instructionNextBtn.onClick.RemoveAllListeners();
instructionNextBtn.onClick.AddListener (delegate {
    InstructionMessages (displayMessage);
});
while (displayMessage < instructions) {
    yield return null;
}

Since your listener delegate is a closure it actually closes over your “displayMessage” variable so it should always receive the current value.