I am programming a task in VR where the user hears an audio file with a certain amount of numbers and needs to press a key after that. If he did it right then he should press "r" and an audio file that is one number longer will be played. If he did it wrong he should press "w" and if it was his first wrong answer after a right answer an audio file will be played that has the same amount of numbers than before. If he did it wrong and already did it wrong right before that the amount of numbers is reduced by one.
In total there will be 10 audio files which is why I decided to use a for loop.
But now I don't know how I can make the for loop wait for the user input. I've also read that it is in general not god to use a for loop when you have to wait for a user input but I don't know what else I can do.
Here is my code so far:
IEnumerator playDSBtask()
{
bool secondWrong = false;
fillList();
for (int i = 0; i < 10; i = i 1)
{
List<AudioSource> x = chooseList(score);
AudioSource myAudio = x[0];
float duration = myAudio.clip.length;
myAudio.GetComponent<AudioSource>();
myAudio.Play();
yield return new WaitForSeconds(duration 5);
if (Input.GetKeyDown("r"))
{
score ;
secondWrong = false;
}
else if (Input.GetKeyDown("f") && secondWrong == false)
{
secondWrong = true;
}
else if (Input.GetKeyDown("f") && secondWrong == true)
{
score--;
}
x.Remove(myAudio);
}
}
But this won't work since the for loop will just continue if none of the if or else if statements are true and therefor executed.
CodePudding user response:
Using a for loop in your case is totally fine since it is in a Coroutine where you yield inside of it so there will be no endless loop and therefore freeze of the main thread.
You could probably use WaitUntil
something like
...
yield return new WaitForSeconds(duration 5);
// Wait until any o the expected inputs is pressed
yield return WaitUntil(() => Input.GetKeyDown("r") || Input.GetKeyDown("f"));
// then check which one exactly
if (Input.GetKeyDown("r"))
{
...
alternatively this could also be done in a more generic way but also more error prone
...
yield return new WaitForSeconds(duration 5);
// wait until something breaks out of the loop
while(true)
{
// check if any key was pressed
if(Input.anyKeyDown)
{
// handle r key
if (Input.GetKeyDown("r"))
{
score ;
secondWrong = false;
// important!
break;
}
else if (Input.GetKeyDown("f"))
{
if(!secondWrong)
{
secondWrong = true;
}
else
{
score--;
}
// Important!
break;
}
}
// if nothing called break wait a frame and check again
yield return null;
}
x.Remove(myAudio);
...
In general you might want to use KeyCode.F
and KeyCode.R
instead of strings.
From a UX perpective though you would either want to reduce the 5 seconds wait or/and show some kind of UI feedback for when user input is handled/awaited.