2012-08-12 114 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