web-dev-qa-db-fra.com

Comment faire en sorte que le script attend / dorme d'une manière simple dans l'unité

Comment peut mettre entre le TextUI.text = .... une fonction de veille, pour attendre 3 secondes entre chaque phrase?

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

J'ai déjà essayé diverses choses mais je n'ai pas travaillé, par exemple:

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

En bash serait:

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

mais je ne peux pas comprendre comment je fais cela dans Unity avec C #

20
DiogoSaraiva

Il y a plusieurs façons d'attendre dans Unity. C’est très simple, mais je pense que cela vaut la peine de couvrir la plupart des façons de procéder:

1 . Avec une coroutine et WaitForSeconds .

Le est de loin le moyen le plus simple. Mettez tout le code que vous devez attendre pendant un certain temps dans une fonction de coroutine, puis vous pouvez attendre avec WaitForSeconds . Notez que dans la fonction coroutine, vous appelez la fonction avec StartCoroutine(yourFunction).

L'exemple ci-dessous fera pivoter de 90 degrés, attendra 4 secondes, fera pivoter de 40 degrés et attendra pendant 2 secondes, puis finalement fera pivoter de 20 degrés

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 . Avec une coroutine et WaitForSecondsRealtime .

La seule différence entre WaitForSeconds et WaitForSecondsRealtime est que WaitForSecondsRealtime utilise un temps d’attente non échelonné, ce qui signifie que lorsqu’une pause dans un jeu avec Time.timeScale, Le WaitForSecondsRealtime la fonction ne serait pas affectée mais WaitForSeconds le serait.

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

Attendez et soyez toujours capable de voir combien de temps vous avez attendu:

3 . Avec un coroutine et incrémentant une variable chaque image avec Time.deltaTime .

Un bon exemple de cela est lorsque vous avez besoin que la minuterie affiche à l'écran combien de temps elle a attendu. Fondamentalement, comme une minuterie.

C'est aussi bien quand vous voulez interrompre l'attente/dormir avec une variable boolean quand c'est vrai. C'est ici que yield break; Peut être utilisé.

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

Vous pouvez toujours simplifier cela en déplaçant la boucle while dans une autre fonction de coroutine et en la renvoyant. Vous pourrez également la voir compter et même interrompre le compteur.

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;
    }
}

Attendez/veillez jusqu'à ce que la variable change ou soit égale à une autre valeur :

4 . Avec une coroutine et la fonction WaitUntil :

Attendez que la condition devienne true. Un exemple est une fonction qui attend que le score du joueur soit 100 Puis charge le niveau suivant.

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 . Avec une coroutine et la fonction WaitWhile .

Attendez qu'une condition soit true. Un exemple est lorsque vous souhaitez quitter l'application lorsque vous appuyez sur la touche Échap.

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 . Avec la fonction Invoke :

Vous pouvez appeler dire à Unity d'appeler la fonction dans le futur. Lorsque vous appelez la fonction Invoke, vous pouvez attendre longtemps avant d'appeler cette fonction avec son deuxième paramètre. L'exemple ci-dessous appelle la fonction feedDog() après 5 Secondes, le Invoke est appelé.

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

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

7 . Avec la fonction Update() et Time.deltaTime .

C'est comme # 3 sauf qu'il n'utilise pas de coroutine. Il utilise la fonction Update.

Le problème, c’est qu’il faut tant de variables pour ne pas s’exécuter à chaque fois, mais une seule fois, une fois le délai écoulé, après l’attente.

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

Il existe encore d’autres moyens d’attendre dans Unity, mais vous devez absolument connaître ceux mentionnés ci-dessus, car cela facilite la création de jeux dans Unity. Quand utiliser chacun dépend des circonstances.

Pour votre problème particulier, voici la solution:

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

Et pour appeler/démarrer la fonction de coroutine depuis votre fonction de démarrage ou de mise à jour, vous l’appelez avec

StartCoroutine (showTextFuntion());
44
Programmer

Vous avez eu raison d'utiliser WaitForSeconds. Mais je suppose que vous avez essayé de l'utiliser sans coroutines. Voilà comment cela devrait fonctionner:

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);
}
6
Max Yankov

Avec .Net 4.x, vous pouvez utiliser un modèle asynchrone basé sur les tâches (TAP) pour atteindre cet objectif:

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

ceci est une fonctionnalité à utiliser. Net 4.x avec Unity s'il vous plaît voir ce lien pour la description à ce sujet

et ce lien pour l'exemple de projet et le comparer avec coroutine

Mais attention, la documentation indique que Cela ne remplace pas totalement la coroutine

1
etzl