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

时间:2015-05-05 14:56:29

标签: 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
.....

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

进行此操作的

7 个答案:

答案 0 :(得分:39)

有许多方法可以在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变量中断等待/睡眠时它也很好。这是可以使用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 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功能:

您可以在将来调用tell Unity来调用函数。当您调用Invoke函数时,您可以在将该函数调用到其第二个参数之前传递等待时间。以下示例将在调用feedDog() 5秒后调用Invoke函数。

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

答案 1 :(得分:5)

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

答案 2 :(得分:1)

使用.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.");
    }
}

这是将.Net 4.x与Unity一起使用的功能,请参见this link for description about it

this link for sample project and compare it with coroutine

但请注意,文档指出这不能完全用协程代替

答案 3 :(得分:0)

这是没有StartCoroutine的更简单方法:

float t = 0f;
float waittime = 1f;

并在Update / FixedUpdate中:

if (t < 0){
    t += Time.deltaTIme / waittime;
    yield return t;
}

答案 4 :(得分:-1)

您可以

        float Lasttime;
        public float Sec = 3f;
        public int Num;
        void Start(){
        ExampleStart();
        }
        public void ExampleStart(){
        Lasttime = Time.time;
        }
        void Update{

        if(Time.time - Lasttime > sec){
//           if(Num == step){
//             Yourcode
//You Can Change Sec with => sec = YOURTIME(Float)
//             Num++;
//            ExampleStart();
             }
             if(Num == 0){
             TextUI.text = "Welcome to Number Wizard!";
             Num++;
             ExampleStart();
             }
             if(Num == 1){
             TextUI.text = ("The highest number you can pick is " + max);
             Num++;
             ExampleStart();
             }
             if(Num == 2){
             TextUI.text = ("The lowest number you can pick is " + min);
             Num++;
             ExampleStart();
             }
        }

    }  

Khaled开发人员
易于游戏

答案 5 :(得分:-1)

使用异步和等待

public void Start() {
     doTask();
}

 async void doTask() {
        Debug.Log("Long running task started");
        // wait for 5 seconds, update your UI
        await Task.Delay(TimeSpan.FromSeconds(5f));

        // update your UI
        Debug.Log("Long running task has completed");
}

答案 6 :(得分:-1)

//这是我在 Unity 中等待的一些代码的示例,我使用一个值制作并在每次更新时更新它,一旦它成为 if 语句正在寻找的值,它将运行任务。

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

public class EnterCarCollider : MonoBehaviour
{
    public GameObject player;

    //Calls & Delcares vehicle objects
    public GameObject Camera;
    public VehicleControl ascript;
    public Collider enterDriverCollider;
    public Collider parkBreakCollider;
    public GameObject enterVehicleDriverToolTip;

    public int forStayInTime = 32;
    public int timeInActiveTriggeredCollider;

    private void Start()
    {
        ascript = GetComponent<VehicleControl>();
        timeInActiveTriggeredCollider = 0;
    }

    private void OnTriggerStay(Collider other)
    {
        if (forStayInTime <= timeInActiveTriggeredCollider)
        {
            if (Input.GetKey(KeyCode.E))
            {
                ascript.enabled = !ascript.enabled;
                Camera.active = true;
                player.active = false;
                enterDriverCollider.enabled = false;
                parkBreakCollider.enabled = false;
           }
           // TODO: Enter car message
           enterVehicleDriverToolTip.active = true;
        }
        timeInActiveTriggeredCollider++;
    }

    private void OnTriggerExit(Collider other)
    {
        enterVehicleDriverToolTip.active = false;
        timeInActiveTriggeredCollider = 0;
    }

    private void Update()
    {
        if (enterDriverCollider.enabled is false)
        {
            timeInActiveTriggeredCollider = 0;
        }
    }
}