如何使脚本以统一的简单方式等待/睡眠

Dio*_*iva 22 c# sleep wait monodevelop unity-game-engine

如何在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);
Run Code Online (Sandbox Code Playgroud)

我已经尝试了各种各样的东西,但没有奏效,这样:

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);
Run Code Online (Sandbox Code Playgroud)

在bash中将是:

echo "Welcome to Number Wizard!"
sleep 3
echo "The highest number you can pick is 1000"
sleep 3
.....
Run Code Online (Sandbox Code Playgroud)

但我无法弄清楚我是如何在Unity中用C#做的

Pro*_*mer 49

在Unity中有很多方法可以等待.这很简单,但我认为值得涵盖大多数方法来做到这些:

1,带协程和WaitForSeconds.

这是迄今为止最简单的方法.把你需要的所有代码放在一个协程函数中等待一段时间然后就可以等了WaitForSeconds.请注意,在coroutine函数中,您可以使用函数调用该函数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);
}
Run Code Online (Sandbox Code Playgroud)

2,有一个协程和WaitForSecondsRealtime.

之间唯一的区别WaitForSeconds和WaitForSecondsRealtime是WaitForSecondsRealtime为使用非标度的时间来等待,这意味着暂停游戏时Time.timeScale,该WaitForSecondsRealtime功能将不会受到影响,但 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);
}
Run Code Online (Sandbox Code Playgroud)

等等,仍然可以看到你等了多久:

3,使用协程并每帧增加一个变量Time.deltaTime.

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

如果你想在boolean变量为真时中断等待/睡眠,这也很好.这是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);
}
Run Code Online (Sandbox Code Playgroud)

你仍然可以通过将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;
    }
}
Run Code Online (Sandbox Code Playgroud)

等待/睡眠直到变量变化或等于另一个值:

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 Leve");

    //Increment and Load next scene
    nextScene++;
    SceneManager.LoadScene(nextScene);
}
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

6,Invoke具有以下功能:

你可以打电话告诉Unity将来调用函数.调用该Invoke函数时,可以在将该函数调用到其第二个参数之前传递等待时间.下面的示例将在调用秒feedDog()后调用该函数.5Invoke

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

void feedDog()
{
    Debug.Log("Now feeding Dog");
}
Run Code Online (Sandbox Code Playgroud)

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");
}
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以在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);
}
Run Code Online (Sandbox Code Playgroud)

要从您的启动或更新功能调用/启动协同程序功能,您可以使用它来调用它

StartCoroutine (showTextFuntion());
Run Code Online (Sandbox Code Playgroud)

  • 所有这些(调用除外)都是协程。这实际上只是一种方法。 (3认同)
  • @TylerSigi#7使用了“更新”功能。他们中的大多数人都使用协程,但是他们等待的方式是“不同的”。并不是仅仅出于乐趣就添加了它们。在不同的情况下需要使用它们,否则,您将无法获得想要的行为,否则您将最终重新发明轮子,而Unity内置的内置功能可以处理某些问题。 (2认同)

Max*_*kov 6

您正确使用WaitForSeconds。但是我怀疑您尝试在没有协程的情况下使用它。那应该是这样的:

public void SomeMethod()
{
    StartCoroutine(SomeCoroutine());
}

private IEnumerator SomeCoroutine()
{
    TextUI.text = "Welcome to Number Wizard!";
    yield return new WaitForSeconds (3);
    TextUI.text = ("The highest number you can pick is " + max);
    yield return new WaitForSeconds (3);
    TextUI.text = ("The lowest number you can pick is " + min);
}
Run Code Online (Sandbox Code Playgroud)


小智 5

使用 .Net 4.x,您可以使用基于任务的异步模式 (TAP) 来实现这一点:

// .NET 4.x async-await
using UnityEngine;
using System.Threading.Tasks;
public class AsyncAwaitExample : MonoBehaviour
{
     private async void Start()
     {
        Debug.Log("Wait.");
        await WaitOneSecondAsync();
        DoMoreStuff(); // Will not execute until WaitOneSecond has completed
     }
    private async Task WaitOneSecondAsync()
    {
        await Task.Delay(TimeSpan.FromSeconds(1));
        Debug.Log("Finished waiting.");
    }
}
Run Code Online (Sandbox Code Playgroud)

这是将 .Net 4.x 与 Unity 一起使用的功能,请参阅此链接以了解有关它的说明

以及示例项目的此链接并将其与协程进行比较

但是要小心,因为文档说这并不能完全替代协程