3

ICollidableインターフェースを実装するエンティティのリストがあります。このインターフェースは、エンティティ間の衝突を解決するために使用されます。したがって、私のエンティティは次のとおりです。

  • プレイヤー
  • 発射物
  • アイテム
  • タイル

ゲームの更新(約60 t / s)ごとに、リストをクリアし、ゲームの状態に基づいて現在のエンティティを追加しています。私はこれを次の方法で達成しています:

collidableEntities.Clear();
collidableEntities.AddRange(players);
collidableEntities.AddRange(enemies);
collidableEntities.AddRange(projectiles);
collidableEntities.AddRange(items);
collidableEntities.AddRange(camera.VisibleTiles);

表示されているタイルをリストに追加するまで、すべて正常に機能します。ゲームループを実行してから最初の約1〜2秒間は、描画を遅らせる目に見える問題が発生します(レンダリングにジッターが見られるようになります)。文字通り、タイルを追加する行を削除/追加して、ジッターが発生するのと発生しないのを確認できるので、その行に絞り込みました。

私の質問は、なぜですか?VisibleTilesのリストは約450〜500タイルであるため、実際にはそれほど多くのデータではありません。各タイルには、何がどこにレンダリングされるかを決定するためのTexture2D(画像)とVector2(位置)が含まれています。ずっと見ていきますが、頭のてっぺんからは、最初の1〜2秒だけがしゃっくりするのに、その後はスムーズになっている理由がわかりません。

アドバイスをいただければ幸いです。

アップデート

初期容量をおおよその要素数まで増やしてみましたが、違いは見られませんでした。

アップデート

リクエストに応じて、カメラのコードは次のとおりです。VisibleTiles

public List<Tile>
{
    get { return this.visibleTiles; }
}
4

3 に答える 3

5

このようなパフォーマンスの問題が発生した場合、正しい対応は、考えられる原因を推測することではありません。正しい応答は、アプリケーションのプロファイルを作成することです。利用可能なオプションがいくつかあります。StackOverflowで提案を見つけることができると確信しています。

しかし、今日はラッキーだと感じているので、先ほどのアドバイスを無視して、大げさな推測をします。私の推論を説明します。これは、将来このような問題を診断するのに役立つことを願っています。

あなたが説明する問題がゲームプレイの開始時に度だけ発生するという事実は、それがリスト自体の機能や衝突ロジックに固有のものではないと私に信じさせます。もちろん、これは、リスト内のオブジェクトの数がこの期間にわたって基本的に一定であることを前提としています。これらのいずれかが原因である場合は、フレームごとに発生すると予想されます。

したがって、ガベージコレクターが疑われます。ゲームの開始直後、つまり、大量のアセットをすべてメモリにロードした直後に、GCが発生する可能性があります。また、割り当てたオブジェクトは理論的にはエッジを越えてコレクションにプッシュできるため、コード内のランダムなポイントで発生する可能性があります。

私の推測では、ゲームをロードすると、作成するアセットが大量の収集プレッシャーを生成しますが、それでも収集をトリガーするには不十分です。ゲームプレイの過程で(この場合、リストのサイズを変更した結果として)オブジェクトを割り当てると、GCが最終的にアクティブ化することを決定するポイントまで収集圧力が増加し、観察されるジッターが発生します。GCが実行され、適切なオブジェクトがすべて正しい世代に追いやられると、ジッターは停止します。

私が言ったように、これは知識のあるものではありますが、単なる推測です。ただし、テストは簡単です。GC.Collect(2)レンダリングループに入る前に、への呼び出しを追加します。私が正しければ、ジッターはなくなるはずです。

それよりも徹底したい場合(そして私はそれを強くお勧めします)、Microsoftはメモリの問題をデバッグするのに役立つツールであるCLRProfilerを提供しています。このツールは、コレクションが発生している時期とその理由を正確に示します。XNA開発に非常に役立ちます。

于 2012-09-12T16:20:06.477 に答える
1

各世代のサイズをGCが調整するため、1〜2秒かかる場合があります。対応するパフォーマンス カウンターを見て、最初の数秒で大量の Gen1/2 コレクションがあるかどうかを確認します (GC を最小限に抑えることは、ゲームにとって有用な目標です)。

追加のランダムな推測: すべてのオブジェクトはstruct何らかの理由によるものです。そしてとても大きい。そのため、コピーには時間がかかります。(最初の数秒以降の平滑化については説明しません)

ノート:

  • 単一のリストにアイテムをマージする代わりに、すべてのコピーを回避する反復子を作成することを検討してください。
  • プロファイラーを取得する
  • プロセスのパフォーマンス カウンターを確認する方法を学びます。興味深いカテゴリは、メモリ、GC、CPU、ハンドラーです。
于 2012-09-12T16:06:01.700 に答える
0

のオーバーロードされたコンストラクターをList<T>使用して、事前定義されたサイズでリストを初期化できます。

var collidableEntities = new List<object>(500);
于 2012-09-12T15:50:13.410 に答える