L'utilisation des Coroutines avec Unity permet d'exécuter du code en parallèle, sans bloquer l'exécution du thread principal. Voyons au travers de ce tutoriel, appliqué à la création de la zone de FORTNITE, comment utiliser ces Coroutines.
Coroutines avec Unity
Quand une fonction est appelée, le code qu'elle contient est lu d'un trait, sans pause, jusqu'à sa fin. Ainsi le code appelé ne peut avoir lieu que sur une seule frame de la méthode Update() de l'API de Unity.
Une fonction ne peut pas contenir par exemple une suite d'évènements rythmés par des pauses...vu que l'on ne peut pas stopper une frame sans stopper le jeu complet (avec Time.timeScale).
C'est là où entrent en jeu les coroutines avec Unity qui permettent de mettre en pause une exécution du code contenu, pour rendre le contrôle à la boucle principale du jeu, puis ensuite de poursuivre la lecture du du code, là où la lecture avait été mise en pause.
Comment mettre en pause dans une coroutine ?
L'instruction magique yield return en C# permet ce tour de magie...
yield return null;
Ici la lecture du code est mise en pause et reprendra à la prochaine frame.
yield return new WaitForSeconds(1f);
Mais on peut aussi décider du moment où la lecture reprendra et c'est là tout l'interêt !! Dans cet autre exemple le code est mis en pause et reprendra dans une seconde (1f).
Déclarer et lancer une Coroutine
Toute coroutine avec Unity doit retourner un objet de type IEnumerator, avec l'instruction yield return quelque part dans le corps de la coroutine.
Voici comment déclarer une coroutine:
IEnumerator WaitOneFrame() {
//code
yield return null;
//code éventuel
}
Et voici comment lancer cette coroutine "WaitOneFrame" depuis un autre endroit du script :
StartCoroutine(WaitOneFrame());//appel de la coroutine identique à l'appel d'une fonction
Sachez que l'on peut aussi utiliser: StartCoroutine("WaitOneFrame"..mais nous allons y revenir dans un instant.
Passer des paramètres à une Coroutine
Nous pouvons avoir besoin de passer des informations à une coroutine afin qu'elle puisse réaliser ses instructions. Il suffit pour cela de changer la signature de notre Coroutine :
IEnumerator WaitOneFrame(float timeToWait) {
//code
yield return new WaitForSeconds(timeToWait);
//code éventuel
}
Ici nous indiquons un temps d'attente, timeToWait, qui est donc un paramètre de notre coroutine. Ce paramètre est utilisé pour le temps de pause.
L'appel de cette coroutine devient naturellement :
StartCoroutine(WaitOneFrame(2.5f)); //on attendra donc 2,5 secondes
Revenons maintenant sur le choix de l'appel de la coroutine. Il existe deux façons de faire:
- StartCoroutine(nomCoroutine(param1,param2,param3,...)); //autant de paramètres que l'on veut !
- StartCoroutine("nomCoroutine",param1);
La seconde n'acceptant qu'un seul paramètre, la première sera de fait à préférer si on a plus d'un paramètre à transmettre.
Mise en pratique sur les coroutines
Afin de voir une utilisation concrète d'une coroutine, nous allons revenir sur quelques points du tutoriel de la zone de Fortnite.
Principe utilisé
C'est en se basant sur des sphere colliders et des détections de collisions de type trigger que nous allons détecter si le joueur est ou pas dans la zone de la tempête. Cette première partie pose la première scène et place le joueur. La mise en place des colliders est réellement décrite dans la partie 3.
Infliger des dégâts
Afin de pouvoir à temps régulier, infliger des dégâts nous utilisons dans la seconde partie une coroutine manageStormDamage pour gérer ce timing.
IEnumerator manageStormDamage(int value){
while(inStorm){
//apply value damage
//le code du tutoriel vidéo
yield return new WaitForSeconds(2f); // on attend 2 secondes
}
}
Ici le booléen inStorm sera passé à true quand le joueur sera détecté comme étant dans la tempête, et ainsi les dégâts seront répétés toutes les 2 secondes sans pour autant bloquer l'exécution du reste du jeu.
La boucle while permet ainsi "d'enfermer" ce bout de code et de le répéter tant que le booléen est true. De plus la valeur des dégâts est passé en paramètre à la coroutine.
Détecter l'entrée dans la tempête
Dans cette partie nous mettons en place la détection de collision afin de finaliser la gestion de la prise de dégâts quand le joueur se retrouve dans la tempête. Tout est ici basé sur des collisions trigger.
Réduire la zone de tempête
Les deux vidéos suivantes permettent d'implémenter la réduction progressive de la taille de la zone de tempête en utilisant le LERP ainsi qu'une autre coroutine pour gérer la fréquence de réduction de la zone.
Ici encore on utilise le même principe de la boucle while avec une instruction d'attente permettant de réduire progressivement la taille de la zone. De plus couplé au LERP, on obtient un effet très "smooth".
Nous arrivons au terme de ce premier tutoriel sur l'utilisation des Coroutines avec Unity. Les deux exemples de coroutines présentés au travers des vidéos permettent d'en voir le potentiel...ne passez pas à côté !!