1. ホーム
  2. c#

[解決済み] Unityでスクリプトを簡単な方法でwait/sleepさせる方法

2022-01-30 21:30:21

質問

の間にスリープ機能を入れるにはどうしたらよいでしょうか。 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#で行う方法がわかりません。

解決方法は?

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 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 関数の 2 番目のパラメータに、その関数を呼び出すまでの待ち時間を渡すことができます。以下の例では 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);
}

また、start関数やUpdate関数からコルーチン関数を呼び出したり、開始したりする場合は

StartCoroutine (showTextFuntion());