ゲーム内の死んだオブジェクトを効果的に取り除く?


10

forループまたはforeachループ(問題ではない)を使用して、オブジェクトを更新または描画する必要があるときにすべてのオブジェクトをループします。ただし、オブジェクトが強制終了された場合は、コレクションから再度削除してください。

これを行うには、オブジェクトをデッドオブジェクトリストに追加し、すべてが描画および更新されたら、このリストのすべてを調べ、リスト内のオブジェクトも元のソースから削除します。

これを行うより良い方法はありますか?



2
これは、タイトルに「ガベージ」という単語が使用されていることと、これまでの.NETガベージコレクタについての回答にかかわらず、ガベージコレクションとはまったく関係ありません。
Andrew Russell

.NETガベージコレクターとの混同を防ぐため、私は自由に「ガベージ」という単語を「デッド」に実際に変更しました。
Nevermind

ああ、私はそれを知っています。ガベージコレクションの記事は、それらの死んだオブジェクトを使って何をするかということに関係があるため、依然として関連しています。例えば死んだ破片?すべてからリンクを解除し、デフォルトにリセットして、デブリバケットに戻します。
doppelgreener '28

回答:


11

まず第一に、用語。「ガベージリスト」と言うと、ガベージコレクターについて話していると思われます。それを「デッドリスト」と呼びましょう。

あなたがおそらく発見しているので、それゆえあなたの質問ですが、それを繰り返し処理している間、コレクションからアイテムを削除することはできません。コレクションがである場合、List<>そこからアイテムを削除する最も簡単な方法は次のとおりです。

for(int i = list.Count-1; i >= 0; --i)
{
    if(list[i].IsDead)
        list.RemoveAt(i);
}

後方に反復することに注意してください。前方に反復しながらアイテムを削除できますが、面倒でが必要gotoです。でそれを行うことはできませんforeach

更新ループとは別に削除を行うことができます。または、それを更新ループにマージできます。常にRemoveAtループの最後でを実行します-ループのそのポイントの後は、list[i]有効とは見なされません(次の反復で再び有効になります)。

また、各オブジェクトには独自のIsDeadフラグがあることに注意してください(ディスポーザルパターンを使用している場合は、それを作成できますIsDisposed)。実際には、「デッドリスト」を維持する必要はまったくありません。

削除するためにリストを検索する必要がないので、各アイテムにフラグを使用することがパフォーマンスにとって望ましいです。また、設計にとっても望ましいです。つまり、各オブジェクトが死んでいるかどうかを簡単に確認できるため、誤ってメソッドを呼び出さないようにします(これらのオブジェクトが使い捨てパターンを実装ObjectDisposedExceptionしている場合、この場合はスローする可能性があります)。

以外のList<>コレクションがある場合、そのコレクションからデッドアイテムを削除すると、デッドリストの作成が引き続き必要になる場合があります(反復中の削除ができない場合があるため)。私の意見では、IsDeadオブジェクトが削除されるときにリストを維持しようとするのではなく、フラグを探してコレクションを反復することによって、使用される直前にデッドリストを作成する方がデザイン的に優れています。

デッドリストの作成が終了したら、それを実行Clear()し、後で再利用できるように保持しておきます。


それで、使い捨てのパターンはより「効果的」と考えられていますか?
ジョナサンコネル

@ジョナサン:私はあなたの質問を理解していません。IsDeadパターンは、機能的に同一IsDisposed。意味的に使用IsDeadすることは、これらのオブジェクトの描画/更新リストを維持していて、後で削除されたアイテムが削除されることを意味します。処分パターンはそれを意味しません。さらに、廃棄パターン、そのオブジェクト(通常、ゲームプレイオブジェクトには適切ではない)が管理していないリソースを保持している可能性があることを示しています。
Andrew Russell

リバースを使用すると、foreachでそれを行うことができます。
しんぞう2016

0

99.9%の時間、ガベージコレクター(GC)が手間をかけずにすべてを処理します。これらのオブジェクトを削除または無効化したら、その処理を実行してください。クリーンアップには多くの要因(たとえば、メモリのブロックがいくつ割り当てられているか)に依存する待ち時間がありますが、通常はそれについて知る必要はなく、心配する必要もありません。機能するように設計されています。これが、CではなくC#を使用している理由の1つです。

一般にGCパフォーマンスについては、それがボトルネックを作成していることを(プロファイリングを通じて)偶然に知らない限り、あまり気にしないでください。これは、一般的に非常に要求の厳しいゲームでのみ発生します。これが当てはまる場合は、GC.Collect()とそのさまざまな落とし穴を調べて、いつそれを使用するのが適切かを理解してください。"force gc xna"をググリングすることをお勧めします。そこにはたくさんの資料があります。


したがって、Update()コールで毎回使用しているリストがある場合、要素が「null」であるリスト内のすべての要素は自動的にクリーンアップされ、削除されますか?
Mathias Lykkegaard Lorenzen、2011

@Mathiasいいえ。質問に対する私のコメントを参照してください。ガベージコレクターは、コレクションやそのコンテンツを含め、アクセス可能なものを変更しません。
アンドリューラッセル

1
「ゴミ」という単語の不運な選択を除いて、質問はGCとは何の関係もありません。
ネヴァーマインド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.