c# - 如何让脚本以简单的方式统一等待/ sleep

标签 c# unity3d monodevelop sleep wait

如何在 TextUI.text = .... 之间放置休眠功能,以便在每个短语之间等待 3 秒?

public Text GuessUI;
public Text TextUI;

[...truncated...]

TextUI.text = "Welcome to Number Wizard!";
TextUI.text = ("The highest number you can pick is " + max);
TextUI.text = ("The lowest number you can pick is " + min);

我已经尝试过各种方法,但都没有奏效,例如:

TextUI.text = "Welcome to Number Wizard!";
yield WaitForSeconds (3);
TextUI.text = ("The highest number you can pick is " + max);
yield WaitForSeconds (3);
TextUI.text = ("The lowest number you can pick is " + min);

在 bash 中,它将是:

echo "Welcome to Number Wizard!"
sleep 3
echo "The highest number you can pick is 1000"
sleep 3
.....

但我不知道如何使用 C# 在 Unity 中执行此操作

最佳答案

Unity中等待的方式有很多种。它们非常简单,但我认为值得涵盖大多数方法:

1。使用协程和WaitForSeconds .

这是迄今为止最简单的方法。将所有需要等待一段时间的代码放在协程函数中,然后您可以使用 WaitForSeconds 等待.请注意,在协程函数中,您使用 StartCoroutine(yourFunction) 调用函数。

下面的示例将旋转 90 度,等待 4 秒,旋转 40 度并等待 2 秒,然后最后旋转 20 度。

void Start()
{
    StartCoroutine(waiter());
}

IEnumerator waiter()
{
    //Rotate 90 deg
    transform.Rotate(new Vector3(90, 0, 0), Space.World);

    //Wait for 4 seconds
    yield return new WaitForSeconds(4);

    //Rotate 40 deg
    transform.Rotate(new Vector3(40, 0, 0), Space.World);

    //Wait for 2 seconds
    yield return new WaitForSeconds(2);

    //Rotate 20 deg
    transform.Rotate(new Vector3(20, 0, 0), Space.World);
}

2。使用协程和WaitForSecondsRealtime .

WaitForSecondsWaitForSecondsRealtime 之间的唯一区别是 WaitForSecondsRealtime 使用未缩放的时间等待,这意味着当使用 暂停游戏时>Time.timeScaleWaitForSecondsRealtime 函数不会受到影响,但 WaitForSeconds 会受到影响。

void Start()
{
    StartCoroutine(waiter());
}

IEnumerator waiter()
{
    //Rotate 90 deg
    transform.Rotate(new Vector3(90, 0, 0), Space.World);

    //Wait for 4 seconds
    yield return new WaitForSecondsRealtime(4);

    //Rotate 40 deg
    transform.Rotate(new Vector3(40, 0, 0), Space.World);

    //Wait for 2 seconds
    yield return new WaitForSecondsRealtime(2);

    //Rotate 20 deg
    transform.Rotate(new Vector3(20, 0, 0), Space.World);
}

等待,仍然能够看到您等待了多长时间:

3。使用协程并使用 Time.deltaTime 在每一帧递增一个变量.

一个很好的例子是当您需要计时器在屏幕上显示它已经等待了多长时间。基本上就像一个计时器。

当您想要使用 boolean 变量(当它为真时)中断等待/ sleep 时,这也很好。这是可以使用 yield break; 的地方。

bool quit = false;

void Start()
{
    StartCoroutine(waiter());
}

IEnumerator waiter()
{
    float counter = 0;
    //Rotate 90 deg
    transform.Rotate(new Vector3(90, 0, 0), Space.World);

    //Wait for 4 seconds
    float waitTime = 4;
    while (counter < waitTime)
    {
        //Increment Timer until counter >= waitTime
        counter += Time.deltaTime;
        Debug.Log("We have waited for: " + counter + " seconds");
        //Wait for a frame so that Unity doesn't freeze
        //Check if we want to quit this function
        if (quit)
        {
            //Quit function
            yield break;
        }
        yield return null;
    }

    //Rotate 40 deg
    transform.Rotate(new Vector3(40, 0, 0), Space.World);

    //Wait for 2 seconds
    waitTime = 2;
    //Reset counter
    counter = 0;
    while (counter < waitTime)
    {
        //Increment Timer until counter >= waitTime
        counter += Time.deltaTime;
        Debug.Log("We have waited for: " + counter + " seconds");
        //Check if we want to quit this function
        if (quit)
        {
            //Quit function
            yield break;
        }
        //Wait for a frame so that Unity doesn't freeze
        yield return null;
    }

    //Rotate 20 deg
    transform.Rotate(new Vector3(20, 0, 0), Space.World);
}

您仍然可以通过将 while 循环移动到另一个协程函数并产生它来简化它,并且仍然能够看到它计数甚至中断计数器。

bool quit = false;

void Start()
{
    StartCoroutine(waiter());
}

IEnumerator waiter()
{
    //Rotate 90 deg
    transform.Rotate(new Vector3(90, 0, 0), Space.World);

    //Wait for 4 seconds
    float waitTime = 4;
    yield return wait(waitTime);

    //Rotate 40 deg
    transform.Rotate(new Vector3(40, 0, 0), Space.World);

    //Wait for 2 seconds
    waitTime = 2;
    yield return wait(waitTime);

    //Rotate 20 deg
    transform.Rotate(new Vector3(20, 0, 0), Space.World);
}

IEnumerator wait(float waitTime)
{
    float counter = 0;

    while (counter < waitTime)
    {
        //Increment Timer until counter >= waitTime
        counter += Time.deltaTime;
        Debug.Log("We have waited for: " + counter + " seconds");
        if (quit)
        {
            //Quit function
            yield break;
        }
        //Wait for a frame so that Unity doesn't freeze
        yield return null;
    }
}

等待/休眠直到变量改变或等于另一个值:

4。使用协程和 WaitUntil功能:

等待条件变为 true。一个例子是等待玩家得分为 100 然后加载下一个级别的函数。

float playerScore = 0;
int nextScene = 0;

void Start()
{
    StartCoroutine(sceneLoader());
}

IEnumerator sceneLoader()
{
    Debug.Log("Waiting for Player score to be >=100 ");
    yield return new WaitUntil(() => playerScore >= 10);
    Debug.Log("Player score is >=100. Loading next Level");

    //Increment and Load next scene
    nextScene++;
    SceneManager.LoadScene(nextScene);
}

5。使用协程和 WaitWhile功能。

等待条件为 true。例如,当您想要在按下转义键时退出应用。

void Start()
{
    StartCoroutine(inputWaiter());
}

IEnumerator inputWaiter()
{
    Debug.Log("Waiting for the Exit button to be pressed");
    yield return new WaitWhile(() => !Input.GetKeyDown(KeyCode.Escape));
    Debug.Log("Exit button has been pressed. Leaving Application");

    //Exit program
    Quit();
}

void Quit()
{
    #if UNITY_EDITOR
    UnityEditor.EditorApplication.isPlaying = false;
    #else
    Application.Quit();
    #endif
}

6。随着 Invoke功能:

以后可以调用告诉Unity调用函数。当您调用 Invoke 函数时,您可以将调用该函数之前的等待时间传递给它的第二个参数。下面的示例将在调用 Invoke5 秒调用 feedDog() 函数。

void Start()
{
    Invoke("feedDog", 5);
    Debug.Log("Will feed dog after 5 seconds");
}

void feedDog()
{
    Debug.Log("Now feeding Dog");
}

7。使用Update()函数和Time.deltaTime .

它就像#3,只是它不使用协程。它使用 Update 函数。

这个问题是它需要太多的变量,所以它不会每次都运行,而是在等待后计时器结束时只运行一次。

float timer = 0;
bool timerReached = false;

void Update()
{
    if (!timerReached)
        timer += Time.deltaTime;

    if (!timerReached && timer > 5)
    {
        Debug.Log("Done waiting");
        feedDog();

        //Set to false so that We don't run this again
        timerReached = true;
    }
}

void feedDog()
{
    Debug.Log("Now feeding Dog");
}

在 Unity 中还有其他等待方法,但您绝对应该知道上面提到的那些,因为这使得在 Unity 中制作游戏更容易。何时使用每一个取决于具体情况。

对于您的特定问题,这是解决方案:

IEnumerator showTextFuntion()
{
    TextUI.text = "Welcome to Number Wizard!";
    yield return new WaitForSeconds(3f);
    TextUI.text = ("The highest number you can pick is " + max);
    yield return new WaitForSeconds(3f);
    TextUI.text = ("The lowest number you can pick is " + min);
}

要从您的启动或更新函数调用/启动协程函数,您可以调用它

StartCoroutine (showTextFuntion());

关于c# - 如何让脚本以简单的方式统一等待/ sleep ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30056471/

相关文章:

c# - 如何从 asmx Web 服务管理多个 ado.net 数据库连接

c# - 静态初始化器中的 Task.Run

unity3d - 我找不到输入调试器面板

macos - 在 Snow Leopard 上使用 MonoDevelop 开发 GUI 项目

c# - 在 app.config 中配置的 WCF 命名管道不起作用

c# - 在 Visual Studio 2012 中移动 obj 文件夹

c# - 从脚本中清除编辑器控制台日志

c# - Unity3D C# 中的相机旋转问题(可能很容易修复)

macos - OSX 上的 ServiceStack 入门

monodevelop - 在 Xamarin Studio 中隐藏某些警告