Table des matières
1. Avant-propos :
Les coroutines sont un concept très important dans Unity. Nous savons que lors de l'utilisation de Unity pour le développement de jeux, le multithreading n'est généralement pas pris en compte (notez qu'il l'est généralement). Alors, comment gérer certaines exigences en dehors de la tâche principale que Unity nous donne ? sont fournis.
Pourquoi le multithreading n’est-il généralement pas pris en compte dans Unity ?
Parce que dans Unity, les composants, méthodes et objets des objets ne peuvent être obtenus que dans le thread principal. S'ils sont séparés, de nombreuses fonctions de Unity ne peuvent pas être réalisées, donc l'existence du multithread n'a que peu d'importance.
Quelle est la différence entre les threads et les coroutines ?
Pour les coroutines, une seule coroutine peut être exécutée en même temps, tandis que les threads sont simultanés et que plusieurs threads peuvent s'exécuter en même temps. Les
deux ont la même utilisation de la mémoire. Partager le tas et ne pas partager la pile
est en fait le plus avantageux. pour les deux. La clé, la différence la plus simple est que les threads microscopiquement sont parallèles (pour les processeurs multicœurs), tandis que les coroutines sont en série. Cela n'a pas d'importance si vous ne comprenez pas.
2. À propos des coroutines
1. Qu'est-ce qu'une coroutine ?
Coroutine signifie littéralement programme d'assistance. Pendant que la tâche principale est exécutée, nous avons besoin que certaines tâches de branche travaillent ensemble pour obtenir l'effet final. Pour l'expliquer un peu plus clairement, imaginez que nous sommes en train d'exécuter la tâche principale. Nous avons besoin d'une opération qui consomme beaucoup de ressources, si nous implémentons une telle opération dans une seule image, le jeu deviendra très lent. À ce stade, nous pouvons utiliser des coroutines pour terminer le traitement du travail dans une certaine image. affectant l’avancement de la tâche principale.
2. Principe de la coroutine
Tout d'abord, vous devez comprendre que les coroutines ne sont pas des threads. Les coroutines sont toujours exécutées dans le thread principal. Ensuite, vous devez savoir que les coroutines implémentent des fonctions via des itérateurs. Utilisez le mot-clé IEnumerator pour définir une méthode d'itération. au lieu de IEnumerable.
La différence entre les deux :
IEnumerator : est une interface qui implémente la fonction itérateur.
IEnumerable : est une interface encapsulée basée sur IEnumerator. Il existe une méthode GetEnumerator() qui renvoie IEnumerator
dans l'itérateur. . , c'est le principal moyen de réaliser la fonction de notre coroutine. Grâce à cette méthode clé, nous pouvons suspendre l'exécution de la coroutine, enregistrer l'heure et le lieu du prochain démarrage, etc.
Pour une explication détaillée des itérateurs, veuillez vous référer à : Documentation officielle C# pour une description détaillée des itérateurs .
3. Utilisation de coroutines
Malentendu :
si une coroutine exécute presque toutes les images et ne s'arrête pas pendant les opérations de longue durée, il est généralement plus logique de remplacer la coroutine par un rappel Update ou LateUpdate. Par exemple des coroutines de longue durée ou en boucle infinie.
Réduisez autant que possible l'utilisation de l'imbrication : bien que les coroutines imbriquées soient très utiles pour assurer l'organisation et la maintenance du code, l'objet de suivi des coroutines lui-même entraînera une surcharge de mémoire plus élevée.
1. Approche fonctionnelle
Utilisez la fonction de transfert pour démarrer la coroutine :
StartCoroutine(Cor_1());
Arrêtez la coroutine : (❎ Mauvaise utilisation 1)
StopCoroutine(Cor_1());
Je l’ai fait quand je l’ai appris pour la première fois, mais je ne sais pas pourquoi cela n’a pas fonctionné. Plus tard, j'ai réalisé : bien que le même nom de fonction ait été transmis, l'adresse de la fonction transmise à l'arrêt n'était pas l'adresse de la fonction transmise au début ~.
Arrêtez la coroutine : (❎ Mauvaise utilisation 2)
StopCoroutine(”Cor_1“);
Mauvaise utilisation pour les débutants : utilisez la méthode de passage d'une fonction pour démarrer la coroutine et utilisez la méthode de passage d'une chaîne pour arrêter la coroutine.
Donc, si vous utilisez StartCoroutine(Cor_1()); pour démarrer la coroutine, comment pouvez-vous l'arrêter manuellement ? Veuillez continuer à lire…
2. Méthode de nom de fonction
Démarrez la coroutine en passant le nom de la fonction :
StartCoroutine("Cor_1");
Arrêtez la coroutine :
StopCoroutine(”Cor_1“);
Il n'y a aucun problème à l'utiliser de cette façon (je suppose que l'implémentation interne l'enregistre sous la forme de <Key, Value>).
Inconvénients : ne prend en charge que la transmission d'un seul paramètre.
De 1 et 2, nous pouvons conclure que seules l'ouverture et la fermeture sous forme de noms de fonctions sont réalisables, mais cela ne résout pas les problèmes laissés par notre méthode 1. Veuillez continuer à lire...
3. Recevez la valeur de retour
Quelle que soit la méthode suivante utilisée pour démarrer la coroutine, vous pouvez terminer sa valeur de retour pour arrêter la coroutine correspondante ;
private Coroutine stopCor_1;
private Coroutine stopCor_2;
stopCor_1 = StartCoroutine("Cor_1");
stopCor_2 = StartCoroutine(Cor_2());
Arrêtez la coroutine :
StopCoroutine(stopCor_1);
StopCoroutine(stopCor_2);
En utilisant cette méthode de réception des valeurs de retour, nous pouvons arrêter la coroutine en fonction de nos besoins ;
cela résout les problèmes laissés dans les méthodes un et deux.
4. Arrêtez toutes les coroutines
Démarrez la coroutine de quelque manière que ce soit
StartCoroutine("Cor_1");
StartCoroutine(Cor_2());
Vous pouvez utiliser StopAllCoroutines pour arrêter
StopAllCoroutines();
StopAllCoroutines() peut arrêter toutes les coroutines du script actuel.
Choses à noter :
Il est recommandé de l'utiliser avec prudence, car il est possible de créer une nouvelle coroutine lors d'une modification ultérieure de la logique, et de l'arrêter sans être arrêté (ne me demandez pas comment je sais que
vous devez vous assurer que toutes les coroutines le sont ). appeler le script doit être terminé (par exemple : déconnecter et reconnecter) Tous les états doivent être réinitialisés)
5. Désactivez/détruisez les objets du jeu
La désactivation/la destruction de la coroutine des objets de jeu s'arrêtera. Lorsque l'objet est à nouveau activé, la coroutine ne poursuivra pas son exécution.
gameObject.SetActive(false);
//通过销毁游戏对象方式和禁用同效果
//Destroy(gameobject)
Ce n'est pas ça:
script.enabled = false;
C'est-à-dire l'objet de jeu monté par le script caché (il en va de même lorsque son objet parent est masqué).
6. Introduction au rendement :
yield return null; // 下一帧再执行后续代码
yield return 0; //下一帧再执行后续代码
yield return 6;//(任意数字) 下一帧再执行后续代码
yield break; //直接结束该协程的后续操作
yield return asyncOperation;//等异步操作结束后再执行后续代码
yield return StartCoroution(/*某个协程*/);//等待某个协程执行完毕后再执行后续代码
yield return WWW();//等待WWW操作完成后再执行后续代码
yield return new WaitForEndOfFrame();//等待帧结束,等待直到所有的摄像机和GUI被渲染完成后,在该帧显示在屏幕之前执行
yield return new WaitForSeconds(0.3f);//等待0.3秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间会受到Time.timeScale的影响);
yield return new WaitForSecondsRealtime(0.3f);//等待0.3秒,一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后(这里的时间不受到Time.timeScale的影响);
yield return WaitForFixedUpdate();//等待下一次FixedUpdate开始时再执行后续代码
yield return new WaitUntil()//将协同执行直到 当输入的参数(或者委托)为true的时候....如:yield return new WaitUntil(() => frame >= 10);
yield return new WaitWhile()//将协同执行直到 当输入的参数(或者委托)为false的时候.... 如:yield return new WaitWhile(() => frame < 10);
4. Résumé :
- S'il est démarré à l'aide de StartCoroutine(function());, il ne peut être arrêté qu'en recevant la valeur de retour [Aucune limite sur le nombre de paramètres] ;
- S'il est démarré à l'aide du formulaire StartCoroutine("function name");, il peut être arrêté à l'aide du formulaire StopCoroutine("function name"); ou il peut être arrêté en recevant la valeur de retour. [Inconvénient : un seul paramètre peut être transmis]
- Les deux formulaires d'ouverture sont contrôlés par StopAllCoroutines(). StopAllCoroutines() peut arrêter toutes les coroutines du script actuel.
- gameObject.SetActive(false); peut arrêter toutes les coroutines sur ce GameObject, et les coroutines ne continueront pas lorsqu'elles seront réactivées.
- StopCoroutine(function()); script.enabled = false; La coroutine ne peut pas être arrêtée.
5. Choses à noter
Les coroutines doivent être utilisées avec prudence dans les projets réels, car leur utilisation affectera les performances.