2012-02-01 14 views
1

私はXNA用の小さなゲームエンジンを作成しています。現在、エンティティマネージャには、更新とレンダリングが可能なすべてのエンティティのリストがあります。しかし、私はこのリストを 'サブリスト'に分割したいと言います。一部のエンティティではレンダリングが不要なため、レンダリングエンティティを非レンダリングエンティティから分離して、すべてのエンティティを更新する別のリストを維持したいと考えています。だから3つのリストです。C#リスト間の一貫性

リスト間の整合性を簡単に維持する方法はありますか?両方のリストで全く同じオブジェクトが参照されていることを確認するには? (オブジェクトのコピーではありませんか?) C++では、レンダリングするエンティティへのポインタの配列と、存在しないエンティティに対するポインタの配列があります。

問題は実際にはエンティティをこれらのリストに入れておらず、それによって私を捨てることになります。エンティティを破壊するために、私は単に、そのエンティティ内で真の 'dispose' boolを設定します。エンティティマネージャーは、すべてのエンティティをループするとき、 'dispose'がtrueに設定されている場合、そのエンティティへの参照を削除し、参照がそれ以上残っていないため、ガベージクリーナはエンティティを破棄します。私は手動で、Entitiesと何か関係がある各リストを手作業で調べ、そのリストからEntityを削除して、一貫性を保たなければなりませんか?

この「問題」の別の例は、クワッドツリーです。私は2dゲームを持っており、私はすべてのエンティティのためのクワッドツリーを生成します。 2つのグリッド位置の間にあるエンティティは、ツリーの2つのブランチにあります。どのように私は木からそれを削除するだろうか?そのエンティティへの参照をツリー全体で検索しますか?それが事実ならクワッドツリーを持つのはちょっと意味がないようです。

答えて

3

3つのリストの代わりに、1つのリストとそのリストの2つのクエリを考慮してください。ここで

var list = GetYourMainList(); 
var renderableEntities = list.Where(item => item.IsRenderable); 
var nonrenderableEntities = list.Where(item => !item.IsRenderable); 

// work with the queries 
foreach (var item in renderableEntities) 
{ 
    // do whatever 
} 

、あなたは結果がメインリストからストリーミングされます、各クエリを反復することができ、そしてそれらが反復されるように、そのリストへの更新は、クエリの結果に反映されます。注意点は、クエリが反復されている間は、リストを変更(追加または削除)できないということです。

+0

このメソッドを頻繁に呼び出す必要がある場合、これは遅くなるでしょうか? –

+1

@Chris、3つのリストを同時に維持し、それらを同期させたり、サイズを変更したりすることはありませんか?これはパフォーマンスが考慮されているとは言いませんが、Linqクエリを指し示す許容できないパフォーマンスの低下と、複数リストアプローチが実際に高速であることを証明したいと考えています。 –

0

処理の問題については、IDisposableを実装できます。リストの場合、2つのリストを含むクラスを作成し、リスト全体が必要な場合は、2つのリストを列挙する列挙子を実装します。

0

エンティティの周りにラッパーを置くことができます。エンティティの周りにラッパーを置くことで、そのラッパーを削除するときに、比較的簡単にすべての場所から取り除くことができます。

0

複数のリストにアイテムがある場合は、そのアイテムを削除する場合は、それらが存在するすべてのリストからアイテムを削除する必要があります。これを行う簡単な方法は、アイテムをアイテム自体に削除する責任を割り当てることです。例えば、レンダリングアイテムは、RemoveFromLists()を呼び出すと、レンダリングアイテムリストから自身を削除します。

アンソニー・ペグラム(Anthony Pegram)の記述によるクエリの使用は、この複雑さを排除しますが、リストが大きくなると増分更新できないため非効率です。

クォッドツリーについては、各アイテムにそれが発生するクアッドツリーノードのリストを保持させるのが簡単です(アイテムにフィールドを追加したくない場合は、ディクショナリを使用してください)。一定時間内に発生するすべてのノードからそれらを削除するのは簡単です。

0

あなたのエンティティは、処分される前に発射される「処分」イベントを公開することができます。次に、リストのAddメソッドにエンティティを追加してイベントハンドラを登録させると、エンティティが削除される前にそのエンティティがリストから削除されます。

関連する問題