2011-09-07 10 views
6

現在、C#& XNAを使用してタワー防衛ゲームを作成しています。ゲームはしばらくの間スムーズに実行されますが、十分な時間(十分な敵/タワー/弾丸が誕生した後)にプレイした後、ゲームは指数関数的に遅くなるようです。すべてのインスタンスがクリアされても、ラグは引き続き維持されます。XNAゲームラグの決定

私はこれがガベージコレクションと関連しているかもしれないと思っていましたが、テストするために、オブジェクトが収集されたときにすべてのオブジェクトが収集されたときに印刷するデストラクタを書きました。誰かがXNAの遅れやその原因の可能性があるのであれば、私は興味がありますか?

EDIT:これはPC

+0

提案:より良い(全体的な)質問があるかもしれません - >遅延がどこで発生しているかを判断するにはどうすればよいですか?これは多くの異なることによって引き起こされる可能性があるようですが、遅れの問題の根本を特定するためにコードの多くを参照する必要があります – jadarnel27

+0

単純に見越すコードがあまりにも多くあります。私は、理論的な解決策や考えられる原因の遅延をもっと求めています。現在のところ、ネットワークは関与していないので、問題ではありません。 – Johannes

+1

あなたが大きなサブルーチンや疑わしい領域を入力して終了するときに、(デバッグログファイルなどに)タイムスタンプを出力することをお勧めします。この方法で、その時間を失っている場所を知ることができ、問題の方向に向かって作業することができます。 – jadarnel27

答えて

1

のために、私はパフォーマンスをチェックするために使用されてきた二つのものがありますされています。

1)App Hubには、Performance utilityがあり、あなたが改善しているものを特定するのに役立ちます。

2)これはちょっと古いですが、for the Xbox 360 this document helped me a lotです。

更新:また、私はthis Gamefest 2010 presentationを忘れました。それはまた、いくつかのことに行きます。

0

ゲームのループ時間が増えましたか? UpdateループとDrawループの開始点と終了点にストップウォッチを追加します。増加している場合は、スローダウンの原因となるものが見つかるまで、stopwatch.Start()および/またはstopwatch.Stop()を除外してください。それが増加していない場合、それは他の何かによって引き起こされます。

てみコードに次の行を追加する:

SpriteBatch.DrawInt64(Font, GC.GetTotalMemory(false)/1000 /* in kilobytes */, 
POSITION, Color.White, 0f); 

(DrawInt64/32はあなたがここに利用できるごみを発生させずに数字を描画することを可能にするspritebatchには本当に便利な拡張機能である:。http://pastebin.com/pVw66mGyまたちょうどのDrawStringを使用し、 .ToString())。

表示される数値が減少するたびに、ガベージコレクションが実行されます。

+0

GC.CollectionCount()を使用すると、ガベージコレクションが発生しているかどうかを判断する良い方法です。これにより、個々の世代が収集される時期を確認することができます。第0世代コレクションは大したことではないでしょう。パフォーマンスに関しては、第1世代と第2世代のコレクションが懸念されています。 –

1

ガベージコレクションがパフォーマンスに影響を与えることを心配している場合は、使い方を学ぶのに最適なツールの1つがCLR Profilerです。このユーティリティを使用すると、プログラムによって実行されるヒープ割り当てをプロファイルすることができます。これにより、正確にどのメソッドがゴミを生成しているのかを特定できます。文字列を連結し、辞書を列挙型キー、クロージャー、デリゲートなどで索引付けすることで、ヒープに多くの分かりにくいものを割り当てることができることを覚えておいてください。毎秒60+フレームでフレームごとに生成される少しのガベージ適切な状況下で

あなたが説明したことは、私にガベージコレクションの問題のようには聞こえません。 GCは、一般的な収集中であっても、フレームを数個しかドロップさせないように、一般的には十分速いです。つまり、頻繁にマイナーな迷惑なジャークに気づくでしょう。

(警告:これはのみ他のXNAプラットフォームに比べて非常に洗練されたGCを持っているPC上で適用されます。)

あなたはメソッドが完了するまでに最長を取っているかを識別するためにあなたのコードにプロファイラを取り付けてみてください;あなたの問題がGCに関連していない場合、これは参考になるかもしれません。以前は、EQATECを使用しましたが、最近のバージョンでは問題がありました。あなたはそれを試すこともできますし、Googleで代替手段を探すこともできます。

0

あなたはイベントをアンフックすることを忘れていませんか?下の例では、4つのスプライトをリストに追加し、各スプライトはゲームのイベントをフックします。私はスプライトを削除し、イベントを発生させます。

このような状況では、4つのスプライトすべてがまだ有効であり、Gameにはまだ参照があるため、イベントが発生します。

あなたのゲームオブジェクトにイベントを使用している場合、それらをすべて実行中のままにすることができます。

class Game 
{ 
    public event EventHandler SomeEvent; 
    List<Sprite> sprites; 

    public Game() 
    { 
    sprites = new List<Sprite>(); 
    sprites.Add(new Sprite(this)); 
    sprites.Add(new Sprite(this)); 
    sprites.Add(new Sprite(this)); 
    sprites.Add(new Sprite(this)); 

    sprites.RemoveAt(0); 

    EventHandler temp = SomeEvent; 
    if (temp != null) 
    { 
     temp(this, EventArgs.Empty); 
    } 
    } 

    static void Main(string[] args) 
    { 
     Game newProgram = new Game(); 
    } 



    class Sprite 
    { 
     public Sprite(Game gameReference) 
     { 
      gameReference.SomeEvent += new EventHandler(gameReference_SomeEvent); 
     } 

     void gameReference_SomeEvent(object sender, EventArgs e) 
     { 
      Debug.WriteLine("Event"); 
     }  
    }