如何在循环c#中断等待协同程序?

时间:2018-04-09 09:21:14

标签: c# unity3d

我正在制作一个基本的游戏而且我卡住了。这个想法是创建一个随机数字阵列并在屏幕上打印数字,并要求用户根据规则点击按钮。例如,规则可以是:如果数字是偶数则单击左按钮,如果数字是奇数则单击右按钮。用户有2秒钟回答每个号码,两秒钟后打印下一个号码。如果用户在2秒之前单击按钮,则答案将保存在阵列中并打印下一个数字(无需等待2秒钟即可完成)。问题是我无法在循环中使用cancelWait变量实现等待协程。它看起来像在循环中所有协同程序由于某种原因同时被解雇。这是我的代码:

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

 public class DemoGM : MonoBehaviour {

 int[] numberArray = new int[10];
 public Text mainText;
 private float waitSystem;

 // Use this for initialization
 void Start () {
     for (int i = 0; i < 10; i++) {
         numberArray[i] = Random.Range(0, 10);
         print(numberArray[i]);
     }
     StartGame();
 }

 // Update is called once per frame
 void Update () {

 }

 void StartGame() {
     StartCoroutine(PrintNumbers());
 }

 IEnumerator PrintNumbers() {

     mainText.text = "Rule";
     yield return new WaitForSeconds(3);
     for (int i = 0; i < 10; i++) {
         mainText.text = numberArray[i].ToString();
         StartCoroutine(WaitForSecondsOrTap(3));
     }

 }

 public void OddButtonClicked() {
     //Save Answer
     cancelWait();
 }
 public void EvenButtonClicked()
 {
     //Save Answer
     cancelWait();
 }


 IEnumerator WaitForSecondsOrTap(float seconds)
 {
     waitSystem = seconds;
     while (waitSystem > 0.0)
     {
         waitSystem -= Time.deltaTime;
         yield return 0;
     }
 }
 private void cancelWait()
 {
     waitSystem = 0.0f;
 }

}

2 个答案:

答案 0 :(得分:1)

有许多方法可以中断协同程序功能。您可以使用yield break退出协同程序功能。将waitSystem变量设置为0 ,就像你做一样,退出WaitForSecondsOrTap协程功能应该工作,但最好使用StopCoroutine的功能。

启动WaitForSecondsOrTap协程,获取StopCoroutine函数返回的引用,当需要停止它时,将该引用传递给StopCoroutine函数。您也可以将该变量用于yield或等待该协程完成。

  

它看起来像在循环中所有协同程序同时被解雇   某种原因

这是因为您的for循环不等待每个WaitForSecondsOrTap调用完成。要等待每个WaitForSecondsOrTap来电,请将其投放。因此,StartCoroutine(WaitForSecondsOrTap(3));应为yield return StartCoroutine(WaitForSecondsOrTap(3));

这就是代码的样子。它显示了停止corutine的正确方法,并阻止在当前调用完成或返回之前调用WaitForSecondsOrTap。:

Coroutine waitCoroutine;

void StartGame()
{
    StartCoroutine(PrintNumbers());
}

IEnumerator PrintNumbers()
{

    mainText.text = "Rule";
    yield return new WaitForSeconds(3);
    for (int i = 0; i < 10; i++)
    {
        mainText.text = numberArray[i].ToString();

        //stop old coroutine
        cancelWait();

        //Start new one then return a reference of it
        waitCoroutine = StartCoroutine(WaitForSecondsOrTap(3));

        //Wait for this instance of coroutine to finish then continue with the program
        yield return waitCoroutine;
    }

}

public void OddButtonClicked()
{
    //Save Answer
    cancelWait();
}
public void EvenButtonClicked()
{
    //Save Answer
    cancelWait();
}


IEnumerator WaitForSecondsOrTap(float seconds)
{
    waitSystem = seconds;
    while (waitSystem > 0.0)
    {
        waitSystem -= Time.deltaTime;
        yield return 0;
    }
}
private void cancelWait()
{
    if (waitCoroutine != null)
        StopCoroutine(waitCoroutine);
}

答案 1 :(得分:0)

StartCoRoutine()几乎立即返回,所以是的,循环中的所有协程都将立即开始并将同时执行。相反,如果相反,在StartGame()中,您使用重复设置为2秒来启动InvokeRepeating(),并使用索引的类变量调用打印新数字的例程。索引将在打印数字之前或之后递增,以及用户单击鼠标按钮时。此外,无论何时单击鼠标按钮,您都可以使用cancelInovke()取消当前InvokeRepeating(),并为InvokeRepeating()发出新的0初始延迟,并为重复发出2延迟。

我可能在那里遗漏了一些东西,但我认为这会让你接近你所追求的东西。听起来像一个有趣的游戏。