複数のコンテナーにゲームオブジェクトを格納する


7

光でDRY、それだけで一つの容器に関連したゲームオブジェクトのコレクションを格納するのが望ましいと思われます。ただし、さまざまなコンテキストでこれらのオブジェクトのサブコレクションが必要になる場合があります。これらの特定のサブセットを特定のより適切なコンテナに保存するのが賢明な場合があります。これにより、たとえばオブジェクトがゲームの世界から削除された場合など、コンテナー全体でオブジェクトを追跡する作業が増加します。

そのような設計を単純化する可能性は何ですか?そして典型的なトレードオフは何ですか?

説明する:

マルチプレーヤーロールプレイングゲームでは、サーバーは、IDによる検索に適したマップにゲームキャラクターのコレクションを保持する場合があります。

world
    map<id, Character> allCharacters

キャラクターは特定のゲームレベルに常駐することもあります。レベルに存在するすべての文字を識別するために、現在そのレベルに存在する文字を保持する各レベルのコンテナを導入することが適切に思えるかもしれません。このようにして、そのレベルのすべてのキャラクターに共通のロジックを実行できます。

world
    map<id, Character> allCharacters

    [levels]
        level1
           vector<Character> charactersOnPlayfield
        level2
           vector<Character> charactersOnPlayfield
        ...

さらに進んで、キャラクターがワールドと対話するとき、メッセージは範囲内のキャラクターにのみルーティングされるべきです。このインタレスト管理は、各レベルをセルのグリッドに分割することによって達成できます。各セルは、現在その上に立っているキャラクターを格納します。

world
    map<id, Character> allCharacters

    [levels]
        level1
           vector<Character> charactersOnPlayfield
           [cells]
               cell1
                   vector<Character> charactersOnCell
               cell2
                   vector<Character> charactersOnCell
               ...
        level2
           vector<Character> charactersOnPlayfield
           [cells]
               cell1
                   vector<Character> charactersOnCell
               cell2
                   vector<Character> charactersOnCell
               ...
        ...

抽象化のさまざまなレベルにあるCharacterオブジェクトは、オブジェクトの所有権と寿命について注意深く考える必要性をもたらします。

コンテナに格納されているCharacterオブジェクトは当然、コピーではなく参照になることに注意してください。また、ガベージコレクションは行われていないと想定しています。

回答:


6

私は実際にそのような複数のリストを持つことに対してアドバイスし、代わりにある種の信号/スロットライブラリを使用します(基本的にはオブザーバーパターン)を使用して、「このエリア/ゾーンのすべてのオブジェクトで関数を呼び出す」パターンを簡単。

オブジェクトは、自分自身に接続する信号を簡単に管理できます。つまり、移動するたびに、古いスロットを表す信号から切断し、新しいスロットに接続します(粒度が細かい場合)。


または、別のコレクションに基づいて内容を基にする読み取り専用の監視可能/フィルター処理されたコレクションを構築します。または、子コレクション(各「パーティション」を表すもの)またはコレクション全体(集合)の観点から表示できる、パーティション化されたコレクションを構築することもできます。オブジェクトが個別のコレクションに個別のメンバーシップを持つという説得力のある理由がない限り、通常はこれらのアプローチのいずれかを使用します(通常はありません)。どちらの場合も、同時アクセスを考慮する必要があり、おそらくスナップショット/バージョン管理機能が必要になります。
Mike Strobel、2010

3

すべてのキャラクターは、何らかの方法で、それが含まれているすべてのコンテナーを知っている必要があります。これは、明示的(それを参照するコンテナーの実際のリスト)、計算可能(キャラクターの座標が格納され、そこから実際のセルベクトルを導出できる)にすることができます。 )、または音声なし(「文字はこれらの6つのリストのいずれかに保存されている可能性があり、わざわざ追跡するつもりはありません」)。または、3つの任意の組み合わせ。重要な部分は、キャラクターを見ているすべての場所を見つけるのが簡単で効率的であるということです。

allCharactersがそこにマップするなど、ゲーム内のすべてのキャラクターを格納する正規のストレージも必要です。

allCharactersに含まれている場合にのみ、キャラクターは生きています。これをallCharactersから削除したい場合は、それを含むすべてのコンテナーからも削除し(最初の段落のとおり、かなり効率的でなければなりません)、設定は完了です。

これは、ガベージコレクションがないことを前提としています-ガベージコレクションがあれば、ほとんどの場合、GCに処理を任せることで回避できます。リークが発生した場合は、すべてのエンティティを保持する弱参照コンテナを作成し、それを使用して、リークしているエンティティを分析します。


お役に立ててありがとうございます。私はガベージコレクションを想定していないので、質問に追加しました。
jmp97 2010

ゲームプレイロジックをGCに依存できるプラットフォームを使用したことがありません。ほとんどのプラットフォームには、実際に何かを収集する前に、数十フレームの長さの遅延(世代別GCの場合は可変長)があります。Pythonのような一部の言語は非循環参照のファイナライズをすぐに保証しますが、特に死ぬときにそれらをゲームに入れないことは非常にまれです(AとBがお互いを撃ち、1人が死ぬ)。

@Joe、私は実際にゲームプレイロジックに使用することについて話しているわけではありませんが、cruftコレクションの難しい部分に簡単に使用できます。jmp97の仮定では、 "player is still alive"フラグを設定し、単純な条件を "interaction broadcast"システムに追加して、プレーヤーにデータを送信する前に、そのプレーヤーが生きていることを確認できます。(またはそれをデータ構造トラバーサルに焼き付けます。)その時点で、ゲームプレイロジックはその単純なフラグに集中され、後でメモリをクリーンアップするGCに依存することもできます。
ZorbaTHut

2

これまでの経験からの質問に答える際、基本的に次のオプションを確認します。

必要になるたびに、より一般的なコレクションからより具体的なオブジェクトのコレクションを抽出する

  • pro:中央オブジェクトリポジトリ
  • con:計算オーバーヘッド

この質問の例で提供されているように、より具体的なコレクションを専用のコンテナに保存します

  • プロ:クイックルックアップ/事前にソートされたデータ
  • con:より複雑なオブジェクトの追跡

ゲームオブジェクトの/サブセットの特定のパースペクティブにキャッシュを使用する

  • プロ:1と2の間の中間
  • 欠点:問題を複雑にする可能性のあるキャッシング戦略を考案する必要がある

これらのオプションのいずれかを選択するための要因には、

  • 特定のオブジェクトのコレクションが必要となる頻度
  • 複数のコンテナにわたってオブジェクトを追跡するためのコストはどれくらいですか(オブジェクトを削除する場合にのみ関連する可能性があります)

Observerパターンは、オブジェクトの他のサブセットを変更する必要が伝播するのを助けることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.