S’abonner dans OnEnable
Fait partie de la section Architecture de jeu dans Unity du Journey Unity de Coddy. Leçon 13 sur 64.
Un écouteur qui est détruit ne quitte pas l’événement de lui-même. L’événement conserve toujours sa méthode, et le prochain appel à Invoke l’appelle sur le composant détruit. La première utilisation de transform dans cette méthode déclenche une MissingReferenceException et, comme une exception met fin à Invoke, les écouteurs suivants sont eux aussi ignorés. Ainsi, chaque += nécessite un -=, et la paire de méthodes prévue par Unity pour cela est OnEnable et OnDisable :
public class Guard : MonoBehaviour
{
public Alarm alarm;
void OnEnable()
{
alarm.OnTriggered += RunTo;
}
void OnDisable()
{
alarm.OnTriggered -= RunTo;
}
void RunTo(Vector3 spot)
{
transform.LookAt(spot);
}
}Unity appelle OnDisable lorsque l’objet est désactivé avec SetActive(false), lorsque le script est désactivé et lorsque l’objet est détruit, avant OnDestroy. OnEnable s’exécute chaque fois qu’il est réactivé. Avec cette paire, un garde écoute exactement tant qu’il est actif : un garde détruit est retiré de l’événement, un garde désactivé pour une cinématique ignore l’alarme et, une fois réactivé, il écoute à nouveau.
Deux autres associations posent problème. Avec += dans Start et -= dans OnDisable, un garde désactivé puis réactivé n’écoute plus jamais, car Start ne s’exécute qu’une seule fois. Avec += dans OnEnable et sans -=, chaque réactivation ajoute RunTo une fois de plus, et une alarme l’appelle deux fois. Supprimer une méthode qui n’est pas abonnée ne fait rien ; il n’est donc jamais nécessaire de vérifier quoi que ce soit dans -= dans OnDisable.
Défi
FacileFais en sorte que chaque villageois n’écoute la cloche que lorsqu’il est actif.
- Dans
Villager.cs, déplacebell.OnRing += Hop;deStart()vers un nouveauvoid OnEnable(), puis supprimeStart(). - Ajoute
void OnDisable()avecbell.OnRing -= Hop;. « Vérifier » désactive et réactive Cleo pour tester cela.
Appuie sur « Jouer » et sonne quatre fois : Ana rentre chez elle après le deuxième coup, et aucune erreur ne s’affiche. Puis appuie sur « Vérifier ».
Essayez vous-même
using UnityEngine;
public class Villager : MonoBehaviour
{
public Bell bell;
public int ringsToLeave = 3;
public int hops;
void Start()
{
bell.OnRing += Hop;
}
void Update()
{
// retomber au sol après un saut
Vector3 p = transform.position;
transform.position = new Vector3(p.x, Mathf.MoveTowards(p.y, 0.5f, 4f * Time.deltaTime), p.z);
}
void Hop(int ring)
{
hops++;
transform.position += Vector3.up * 0.8f;
if (hops == ringsToLeave)
{
Debug.Log(name + " goes home");
Destroy(gameObject);
}
}
}
Toutes les leçons de Architecture de jeu dans Unity
1Des composants, pas des hiérarchies
De petits composantsUn script de base pour les ennemisComposants abstraitsDes composants qui fonctionnent ensembleRécapitulatif : tourelle modulaireRécapitulatif : canon double4Données sérialisées
Classes sérialisablesListes dans l’InspecteurÉnumérations dans l’InspecteurRécapitulatif : table de butinRécapitulatif : tirer le butin2Les interfaces dans Unity
IDamageableInterfaces et TryGetComponentGetComponentsRécapitulatif : touche d’interactionLe plus proche à portée5ScriptableObjects
Ressources de donnéesStatistiques des armesParamètres partagésSauver le ventLes vagues comme donnéesRécapitulatif : base de données des objetsRécapitulatif : acheter dans la boutique3Événements
Les événements C# dans UnityS’abonner dans OnEnableChamps UnityEventLes événements pilotent l’interfaceRécapitulatif : fenêtre de succèsRécapitulatif : minuteur de la fenêtreEntraînez-vous par vous-même : Playground Unity