如何在unity中用一个简单的方式使脚本等待/睡眠?
计算机/软件
0 405
0
该提问暂无详细描述
收藏
2021-01-23 06:19 更新 gitvrar •  435
共 1 个回答
高赞 时间
0

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

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

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

当你想用一个boolean来中断等待/睡眠时,它也可以完成。

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

    //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函数:

在调用Invoke函数时,可以将调用该函数之前的等待时间传递给它的第二个参数。 下面的示例将在调用Invoke 5秒钟后调用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中制作游戏。在什么情况下使用某一个方法都要视情况而定。

收藏
2021-01-23 07:11 更新 同步 •  1253