条件は次のとおりです。
あなたは両方を持つことはできません。どうして?エンティティ自体より高いレベルのコード(下の例を参照)が、そのエンティティをいつ使用する必要があるかを決定するためです。したがって、同じレベルのコードだけが、エンティティが削除に適しているかどうかを判断できます。
ただし、発生する可能性があるのは、上位レベルのコードがリッスンしているイベントを発生させることにより、エンティティが自身の削除をリクエストできることです。その上位レベルは、この削除要求をリストに格納します。
例1:イベントなし
あなたはあなたの世界のエンティティ間の衝突をチェックしています。これは上位で処理されます。通常は、メインのゲームループで、すべてのエンティティをお互いに対してチェックします。具体的には、この例では、エンティティが他のエンティティと衝突した場合、そのエンティティの内部ロジックだけが、受けたダメージの大きさ、および「期限切れ」かどうかを判断できます。それでは、A、B、C、Dの世界に4つのエンティティが存在する場合の衝突のロジックフローを見てみましょう。Aは、私たちが関係しているエンティティです。
AとBの衝突をチェックします。衝突があります。Aは50%のダメージを受けます。
AとCの衝突をチェックします。衝突があります。Aは50%のダメージを受けます。ダメージが0になったため、Aは「死んだ」と判断します。リストから自分自身を削除します。
Dとの衝突についてAをチェックします。衝突はなかったでしょうが、それだけではありません。エンティティリストがトラバーサル操作の最中に変更されたため、ランタイム例外が発生します。
例2:イベントあり
以前と同じ設定。
AとBの衝突をチェックします。衝突があります。Aは50%のダメージを受けます。
AとCの衝突をチェックします。衝突があります。Aは50%のダメージを受けます。ダメージが0になったため、Aは「死んだ」と判断します。エンティティ管理コードにイベントを発生させて、「すぐに削除」と言います。エンティティ管理コードは、イベントの一部として送信されたエンティティ参照を確認し、削除するエンティティのリストにその参照を格納します。
AとDの衝突をチェックします。衝突はなく、チェックは正常に機能します。
ここで、現在のゲームループの反復の最後に、削除するエンティティのリストを実行し、これらすべてをメインエンティティリストから削除します。
これにより、問題を完全に回避できることがわかります。イベントを使用する必要はありません。シグナルなどを使用できますが、原則は同じです。安全に削除できるようになるまでエンティティを削除しないでください。このアプローチの反対側は、物事をきれいに整然と保つために、追加するエンティティでも同じことを行っています。必ずそれらへの参照を維持し、次のゲームループ反復の開始時にのみ追加してください。
最後に、メインエンティティリストで追加/削除を実行するたびに、削除リストと追加リストの両方をフラッシュすることを忘れないでください。
PS。メインリストから個別に削除することを恐れないでください。これは、エンティティ管理の一部であり、大規模なリストでさえ、トラバースが非常に高速になる傾向があります。