- Home /
Waiting for Input via Coroutine
Hello All,
So I've been working on a rudimentary dialogue system. Basically it works by displaying text sequentially, and to do this I am using a coroutine.
using UnityEngine;
using System.Collections;
public class TalkTrigger : MonoBehaviour {
bool currentlyTalking = false;
public string[] dialogue;
// Use this for initialization
void Start () {
}
void OnTriggerEnter2D() {
//PUT THE STARTER DIALOGUE HERE
GUIManager.PushTextBox(GUIInterface.instance.genericTextBox, GUIInterface.instance.genericText, "press SPACE to talk to me");
currentlyTalking = true;
}
void OnTriggerStay2D(){
if(Input.GetKeyUp(KeyCode.Space) && currentlyTalking == true)
{
Debug.Log("Should be talking now...");
StartCoroutine("DialogueStart");
}
}
//this is where sequential dialogue goes
IEnumerator DialogueStart(){
GUIManager.StartConversation();
foreach(string text in dialogue)
{
yield return StartCoroutine(Dialogue(text);
}
GUIManager.EndConversation();
currentlyTalking = false;
}
IEnumerator Dialogue(string text){
GUIManager.PushTextBox(GUIInterface.instance.genericTextBox, GUIInterface.instance.genericText, text);
yield return new WaitForSeconds(5);
GUIManager.PopTextBox(GUIInterface.instance.genericTextBox, GUIInterface.instance.genericText);
}
}
now this script works as expected, but, when i try to change:
yield return new WaitForSeconds(5);
to
yield return Input.GetKeyDown(KeyCode.Space);
All of the text flies by, and doesn't actually wait for the user's next press.
Is there something about the default input methods that allow this to happen? Is there a way to control the floodgate so that the coroutine pauses at each point I need user input?
Thanks in advance
Answer by iwaldrop · Nov 30, 2013 at 08:52 AM
If you check the scripting reference you'll see that Input.GetKeyDown returns a bool, not an IEnumerator. Since this is the case, you want to use a while loop and yield while that condition is false. Ex:
IEnumerator WaitForKeyDown(KeyCode keyCode)
{
while (!Input.GetKeyDown(keyCode))
yield return null;
}
Now you can wait for whatever kind of input you want by calling this:
yield return StartCoroutine(WaitForKeyDown(KeyCode.Space));
thats still causing erratic cycling behavior when i use that
Looks to me like you might be starting that coroutine that does the dialogue all the time if you aren't careful. You should ensure that the Dialogue coroutine can only be running once.
Wait what am I supposed to do? I did everything up to @whydoidoit made a comment. What do you mean @whydoidoit? How am I supposed to prevent that?
It still just skips the whole inumerator/coroutine.
Tl;dr What is @whydoidoit's solution?
I recommend that you create a new question, reference this issue, and post your code so that we can see what your specific issue might be. It's probably something at the call site; it's probably something simple.
I added one line after the while, because after the input the foreach was passing through one of the array strings without stoping:
IEnumerator WaitFor$$anonymous$$eyDown($$anonymous$$eyCode keyCode)
{
while (!Input.Get$$anonymous$$eyDown(keyCode))
yield return null;
yield return new WaitForFixedUpdate();
}
Yes, that's the usual way how to solve it. However there's no point in using WaitForFixedUpdate. Just do another yield return null;
. Another way is to reverse the order by doing a do-while loop ins$$anonymous$$d of a normal while. That way you always wait at least once before you check the key:
do
{
yield return null;
} while (!Input.Get$$anonymous$$eyDown(keyCode));
Answer by Pablomon · Jun 14, 2018 at 12:21 AM
Inside your coroutine you could do this: yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.A));
Your answer
Follow this Question
Related Questions
Very fast User Input Game in Unity 1 Answer
Help In Making a SphereCast for 3D Tire! Working RayCast Script included! 0 Answers
Input management with coroutines in a fighting game. 0 Answers
Why is my function/coroutine executing a second time? 0 Answers
Checking Input on 2 different coroutines at the same time 1 Answer