【问题标题】:Making a for loop wait for user Input使 for 循环等待用户输入
【发布时间】:2021-12-08 07:33:34
【问题描述】:

我在 VR 中编写一个任务,用户听到带有一定数量数字的音频文件,然后需要按一个键。如果他做得对,那么他应该按“r”,然后播放一个多一个数字的音频文件。如果他做错了,他应该按“w”,如果这是他在正确答案之后的第一个错误答案,将播放一个与以前具有相同数量的数字的音频文件。如果他做错了并且在此之前已经做错了,那么数字的数量就会减少一。

总共会有 10 个音频文件,这就是我决定使用 for 循环的原因。

但现在我不知道如何让 for 循环等待用户输入。我还读到,当您必须等待用户输入但我不知道我还能做什么时,使用 for 循环通常不是上帝。

到目前为止,这是我的代码:

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);
    }
}

但这不起作用,因为如果 if 或 else if 语句都不为真并因此执行,则 for 循环将继续。

【问题讨论】:

    标签: c# for-loop unity3d user-input


    【解决方案1】:

    在你的情况下使用 for 循环是完全可以的,因为它在一个协程中,你可以在其中产生它,所以不会有无限循环,因此会冻结主线程。

    你可能会使用 WaitUntil 之类的东西

    ...
    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"))
    {
    ...
    

    或者,这也可以以更通用的方式完成,但也更容易出错

    ...
    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);
    ...
    

    一般来说,您可能希望使用KeyCode.FKeyCode.R 来代替字符串。


    从用户体验的角度来看,尽管您可能希望减少 5 秒的等待时间或/并在处理/等待用户输入时显示某种 UI 反馈。

    【讨论】:

    • 非常感谢您的回答!我现在就试试!是否有可能必须在协程中产生语句,或者我必须结合 waitForSeconds 和 WaitUntil 语句?
    • @sarahrht 您可以根据需要在IEnumerator 中添加任意数量的yield 行。或者你的意思是你想同时检查这两个条件,所以等到有用户输入或时间已经过去?
    • 是的,我的意思是如果可以有尽可能多的屈服线。非常感谢您的帮助,现在可以使用了!
    • @sarahrht 请记住接受解决了您问题的答案 ()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    相关资源
    最近更新 更多