2012-08-12 109 views
7

所以我想將我的PC遊戲轉換到Xbox 360上運行。它在PC上運行得非常好,帶有Intel Core 2 Quad @ 2.40Ghz和Radeon 4850 512MB。我把它移植到Xbox上,並且馬上就出現了關於導入列表的不變性和繼承問題,所以我簡單地使用了名爲.Cast <>()的LINQ方法。PC XNA遊戲轉換爲Xbox 360 - 巨大的性能問題

如果該方法是需要一個大的開銷,讓我知道,因爲我不能部署在360由於某種原因性能分析,很可能是因爲它起着對360

然後另一個問題來了,它是一個不錯的System.OutOfMemoryException。我的天空盒紋理是4096x4096,所以減少一半就消除了這個錯誤。奇怪的是,他們只有3MB x 6,所以它不應該使用512MB的可用空間。

因此,當所有這些問題都被清除後,每2秒引入一個不錯的1幀。無論如何,它在遊戲1分鐘後會崩潰,即「代碼4」。

它就像一個簡報。以下是來自PC遊戲的一些性能分析圖像。他們並不壞。

CPU:http://i.imgur.com/JYx7Z.png RAM:http://i.imgur.com/C29KN.png 72%= 150MB介意你。

我希望這裏的任何人都有這方面的經驗。坦率地說,我是全部耳朵。

回答

11

性能問題的根本原因幾乎肯定是因爲您在運行遊戲時分配內存(啓動後,在Draw/Update循環中)。

在Windows上,這很好。 Windows上的垃圾收集器是世代的(只會在可能的情況下清理新對象)並且速度非常快。它選擇跑步的時候也很聰明。

另一方面,Xbox 360上的垃圾收集器完全是垃圾。它運行每分配1MB的內存。它在運行時檢查整個託管堆。啓動起來很慢。

所以答案是在遊戲處於運行狀態時決不分配內存。

關於此here有一篇很好的博客文章。 (這也說明了替代從未分配的內存 - 這是降低堆的複雜性 - 這實在是很難實現,我不建議這樣做。)

  • 你將需要刪除的東西像LINQ,如它創建的查詢對象就是堆對象,就像它經常需要的委託一樣。改用簡單的循環。
  • 如果您在繪圖/更新中分配自己的引用類型,則必須在可能的情況下轉換爲使用值類型或添加對象池。
  • 創建string對象是內存分配的另一個常見來源 - 相反,您可以重新使用StringBuilder並直接進行渲染。
  • 將東西(特別是數字)轉換爲字符串,即使對於StringBuilder也會分配內存。您需要編寫/查找無分配的替代方案。My answer to this similar question有一個用於int

診斷你在哪裏分配內存的最佳方式是與CLR Profiler在Windows上運行你的遊戲。這會告訴你何時何地分配內存。只需優化,直到你沒有分配。 (或直到你可靠地爲每個級別/地圖/房間/任何地方分配低於1MB,並且在適合口吃的時間內執行手動GC--如靜態加載屏幕或淡入黑色)

代碼4是未處理的異常。您需要安裝輸出消息的頂級異常處理程序,或者在調試器中運行您的遊戲以確定原因。

最後:這可能是壓縮的大小的紋理(使用PNG或JPEG或類似的)。如果你的紋理是未壓縮的,4096×4096×6×4字節= 384MB。這是巨大的 - 難怪你沒有記憶。您可以使用DXT1壓縮它們,並將它們縮小6倍(instructionswiki)。你也可以降低他們的分辨率。你是否需要底面?

+1

感謝大家,經過大量的搜索後,我發現了一個類似的答案,當我運行我的CLR配置文件時,我發現我每幀分配大約60MB ...並不好。這是因爲我將我遊戲中的所有可碰撞對象添加到列表中,然後將它們放入每幀碰撞線程中。我可以把它作爲一個靜態列表,在那裏它只是一個參考,我可能會這樣做,但後來我認爲碰撞滯後的可能性。但我想這是唯一的選擇。 – 2012-08-12 13:27:26