Ecco le tue condizioni:
Altri oggetti possono ancora dipendere dall'entità rimossa, dopo che è stata rimossa.
Desideri che solo l'entità specifichi la propria rimozione.
Non puoi avere entrambi. Perché? Perché il codice a un livello superiore rispetto alla tua stessa entità (vedi esempi sotto) decide quando deve essere usata quell'entità. Di conseguenza, solo il codice a quello stesso livello può determinare se la tua entità è adatta alla rimozione o meno.
Tuttavia , ciò che può accadere è che l'entità può richiedere la propria rimozione, attivando un evento che il codice di livello superiore sta ascoltando. Il livello superiore memorizza quindi questa richiesta di rimozione in un elenco.
Esempio 1: senza eventi
Stai verificando le collisioni tra entità nel tuo mondo. Questo è gestito più in alto, di solito nel tuo ciclo di gioco principale, che controlla ogni entità l'una contro l'altra. In questo esempio in particolare, quando un'entità si scontra con un'altra, solo la logica interna di quell'entità può determinare quanto danno ha subito e se è "scaduto" o meno. Quindi seguiamo il flusso logico per le collisioni in cui hai quattro entità nel tuo mondo, A, B, C e D. A è la nostra entità di cui ci occupiamo.
Controlliamo A per collisione con B. C'è una collisione. A subisce danni al 50%.
Controlliamo A per collisione con C. C'è una collisione. A subisce danni al 50%. Poiché il danno raggiunge 0, A determina che è "morto". Si rimuove dall'elenco.
Controlliamo A per la collisione con D. Non ci sarebbe stata alcuna collisione, ma non arriverai mai così lontano: ottieni un'eccezione di runtime perché il tuo elenco di entità è stato modificato nel mezzo di un'operazione traveral.
Esempio 2: con eventi
Stessa configurazione di prima.
Controlliamo A per collisione con B. C'è una collisione. A subisce danni al 50%.
Controlliamo A per collisione con C. C'è una collisione. A subisce danni al 50%. Poiché il danno raggiunge 0, A determina che è "morto". Genera un evento al codice di gestione dell'entità per dire "Rimuovimi al più presto". Il codice di gestione delle entità esamina il riferimento dell'entità inviato come parte dell'evento e memorizza tale riferimento in un elenco di entità da rimuovere.
Controlliamo A per collisioni con D. Non ci sono collisioni e il controllo funziona bene.
Ora, alla fine dell'attuale iterazione del ciclo di gioco , scorrere l'elenco delle entità da rimuovere e rimuoverle tutte dall'elenco delle entità principali.
Puoi vedere come questo evita del tutto il problema. Non è necessario utilizzare eventi, è possibile utilizzare segnali o qualcos'altro, ma il principio è lo stesso: non rimuovere entità fino a quando non è possibile farlo in modo sicuro. Il rovescio della medaglia di questo approccio, per mantenere le cose pulite e ordinate, sta facendo lo stesso con le entità da aggiungere: assicurati di conservare i riferimenti ad esse e aggiungili solo all'inizio della prossima iterazione del ciclo di gioco.
Infine, non dimenticare di eliminare sia gli elenchi da rimuovere che quelli da aggiungere, ogni volta che li usi per eseguire aggiunte / rimozioni nell'elenco delle entità principali.
PS. Non abbiate paura di cercare nella vostra lista principale per effettuare traslochi individuali. Fa parte della gestione delle entità, e anche gli elenchi di grandi dimensioni tendono ad essere molto veloci da attraversare - dopotutto, è per questo che sono progettati.