Aquí están tus condiciones:
Otros objetos aún pueden depender de su entidad eliminada, después de que se elimine.
Solo desea que la entidad especifique su propia eliminación.
No puedes tener ambos. ¿Por qué? Debido a que el código en un nivel más alto que su propia entidad (vea los ejemplos a continuación) decide cuándo debe usarse esa entidad. En consecuencia, solo el código en ese mismo nivel puede determinar si su entidad es apta para su eliminación o no.
Sin embargo , lo que puede suceder es que la entidad puede solicitar su propia eliminación, activando un evento que el código de nivel superior está escuchando. Ese nivel superior luego almacena esta solicitud de eliminación en una lista.
Ejemplo 1: sin eventos
Estás comprobando colisiones entre entidades en tu mundo. Esto se maneja más arriba, generalmente en el ciclo principal del juego, que compara a cada entidad entre sí. En este ejemplo específicamente, cuando una entidad colisiona con otra, solo la lógica interna de esa entidad puede determinar cuánto daño ha sufrido y si ha "caducado" o no. Entonces, sigamos el flujo lógico para colisiones en las que tiene cuatro entidades en su mundo, A, B, C y D. A es nuestra entidad que nos preocupa.
Verificamos A para colisión con B. Hay una colisión. A recibe daño 50%.
Verificamos A para colisión con C. Hay una colisión. A recibe daño 50%. Como el daño llega a 0, A determina que ha "muerto". Se elimina de la lista.
Verificamos A para colisión con D. No habría habido colisión, pero nunca llegarás tan lejos: obtienes una excepción de tiempo de ejecución porque tu lista de entidades se ha modificado en medio de una operación de viaje.
Ejemplo 2: con eventos
La misma configuración que antes.
Verificamos A para colisión con B. Hay una colisión. A recibe daño 50%.
Verificamos A para colisión con C. Hay una colisión. A recibe daño 50%. Como el daño llega a 0, A determina que ha "muerto". Dispara un evento al código de gestión de la entidad para decir: "Quitarme lo antes posible". El código de gestión de la entidad examina la referencia de la entidad enviada como parte del evento y almacena esa referencia en una lista de entidades que se eliminarán.
Verificamos A para colisión con D. No hay colisión, y la verificación funciona bien.
Ahora, al final de la iteración del bucle del juego actual , recorra la lista de entidades que se eliminarán y elimine cada una de ellas de su lista de entidades principales.
Puedes ver cómo esto evita el problema por completo. No necesita usar eventos, puede usar señales u otra cosa, pero el principio es el mismo: no elimine entidades hasta que pueda hacerlo de manera segura. La otra cara de este enfoque, para mantener las cosas limpias y ordenadas, es hacer lo mismo con las entidades para agregar: asegúrese de mantener referencias a ellas y solo agréguelas al comienzo de la próxima iteración del bucle del juego.
Por último, no olvide eliminar las listas para eliminar y agregar, cada vez que las use para realizar adiciones / eliminaciones en su lista de entidades principal.
PD. No tenga miedo de buscar en su lista principal para realizar mudanzas individuales. Es parte integrante de la gestión de entidades, e incluso las listas masivas tienden a ser muy rápidas de recorrer, después de todo, para eso están diseñadas.