Voici vos conditions:
D'autres objets peuvent encore dépendre de votre entité supprimée, après sa suppression.
Vous souhaitez que l'entité spécifie sa propre suppression.
Vous ne pouvez pas avoir les deux. Pourquoi? Parce que le code à un niveau supérieur à votre entité elle-même (voir les exemples ci-dessous) décide quand cette entité doit être utilisée. Par conséquent, seul le code de ce même niveau peut déterminer si votre entité est apte à être supprimée ou non.
Cependant , ce qui peut arriver, c'est que l'entité peut demander sa propre suppression, en déclenchant un événement que le code de niveau supérieur écoute. Ce niveau supérieur stocke ensuite cette demande de suppression dans une liste.
Exemple 1: sans événements
Vous contrôlez les collisions entre les entités de votre monde. Ceci est géré plus haut, généralement dans votre boucle de jeu principale, qui vérifie chaque entité les unes par rapport aux autres. Dans cet exemple en particulier, lorsqu'une entité entre en collision avec une autre, seule la logique interne de cette entité peut déterminer les dommages qu'elle a subis et si elle a «expiré» ou non. Permet donc de suivre le flux logique des collisions où vous avez quatre entités dans votre monde, A, B, C et D. A est notre entité qui nous intéresse.
Nous vérifions A pour une collision avec B. Il y a une collision. A subit 50% de dégâts.
Nous vérifions A pour une collision avec C. Il y a une collision. A subit 50% de dégâts. Parce que les dégâts atteignent 0, A détermine qu'il est "mort". Il se retire de la liste.
Nous vérifions A pour une collision avec D. Il n'y aurait pas eu de collision, mais vous n'irez jamais jusque-là: vous obtenez une exception d'exécution car votre liste d'entités a été modifiée au milieu d'une opération de traveral.
Exemple 2: avec événements
Même configuration que précédemment.
Nous vérifions A pour une collision avec B. Il y a une collision. A subit 50% de dégâts.
Nous vérifions A pour une collision avec C. Il y a une collision. A subit 50% de dégâts. Parce que les dégâts atteignent 0, A détermine qu'il est "mort". Il déclenche un événement dans le code de gestion d'entité pour dire «Supprimez-moi dès que possible». Le code de gestion d'entité examine la référence d'entité envoyée dans le cadre de l'événement et stocke cette référence dans une liste d'entités à supprimer.
Nous vérifions A pour la collision avec D. Il n'y a pas de collision, et la vérification fonctionne très bien.
À la toute fin de l'itération de boucle de jeu en cours , parcourez la liste des entités à supprimer et supprimez chacune d'elles de votre liste d'entités principale.
Vous pouvez voir comment cela évite complètement le problème. Vous n'avez pas besoin d'utiliser des événements, vous pouvez utiliser des signaux ou autre chose, mais le principe est le même - ne supprimez pas d'entités avant de pouvoir le faire en toute sécurité. Le revers de cette approche, pour garder les choses propres et ordonnées, fait de même avec les entités à ajouter - assurez-vous de conserver des références à elles, et ne les ajoutez qu'au début de la prochaine itération de boucle de jeu.
Enfin, n'oubliez pas de vider vos listes à supprimer et à ajouter, chaque fois que vous les utilisez pour effectuer des ajouts / suppressions sur votre liste d'entités principale.
PS. N'ayez pas peur de chercher dans votre liste principale des déménagements individuels. Cela fait partie intégrante de la gestion des entités, et même des listes massives ont tendance à être très rapides à parcourir - après tout, c'est pour cela qu'elles sont conçues.