2011-09-07 137 views
6

我目前正在創建一個使用C的塔防遊戲#& XNA。遊戲運行良好,平穩一段時間,但玩了很長時間(足夠的敵人/塔/子彈產生後),遊戲似乎成倍減速。即使所有實例都被清除,滯後仍然存在。我開始以爲這可能與垃圾收集有關(也許它的確如此),但爲了測試它,我收集了一個對象並且一切看起來都很好(收集了所有對象)時編寫了析構函數來打印。所以我很好奇,如果任何人有任何XNA滯後的經驗和可能的原因呢?確定XNA遊戲滯後

編輯:這是PC

+0

建議:一個更好的(總體)問題可能是 - >我能做些什麼來確定滯後發生的地方?看起來這可能是由許多不同的事情引起的,我們必須看到很多代碼才能確定滯後問題的根源 – jadarnel27

+0

有太多代碼可以簡單地查看。我更多地要求理論解決方案或可能的原因滯後。目前沒有網絡涉及,所以不應該是一個問題。 – Johannes

+1

我建議的一件事就是在進入和退出較大的子程序/懷疑區域時打印(到調試日誌文件或其他內容)時間戳。通過這種方式,你可以看到你在哪裏丟失了時間,並朝着這個問題前進 – jadarnel27

回答

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或者只是使用束帶和.ToString())。

每當顯示的數字減少時,就會運行垃圾收集。

+0

確定垃圾收集是否發生的更好方法是使用GC.CollectionCount()。這將允許您查看收集每一代的時間。第0代收集可能不是什麼大問題;第一代和第二代系列在性能方面更受關注。 –

1

如果您擔心垃圾收集會影響性能,您可以學習使用的最佳工具之一是CLR Profiler。該實用程序允許您分析程序執行的堆分配,以便您可以確定哪些方法正在生成垃圾。請記住,許多非顯而易見的事情可以分配到堆上:連接字符串,使用枚舉鍵索引字典,關閉,委託等。即使每幀以每秒60幀以上的速度產生一次垃圾,也可以快速累積在適當的情況下。

這就是說,你所描述的並不像聽我說的垃圾回收問題。即使在完整的收集過程中,GC的速度通常也足夠快,只會導致幾幀丟失 - 換句話說,您會經常注意到一個次要的,令人討厭的混蛋,但不會持續放緩。

(警告:這僅適用於個人電腦,相比其他XNA平臺它有一個非常複雜的GC上。)

你應該嘗試分析器連接到你的代碼,以確定哪些方法耗時最長完成;如果你的問題與GC無關,這可能是有益的。在過去,我使用EQATEC,雖然我有一些更新版本的問題。你可以試試這個,或者你可以在Google上尋找替代方案。

0

你不會忘記解除事件嗎?在下面的示例中,我將4個精靈添加到列表中,每個精靈都會掛鉤遊戲中的事件。然後,我刪除一個精靈,並提出事件。

在這種情況下,所有4個精靈仍然活躍,並獲得他們的事件,因爲在遊戲中仍然有對他們的引用。

只是一個念頭,如果你正在使用你的遊戲對象的事件,你可能會讓它們全部繼續運行。

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"); 
     }  
    }