PC XNA游戏转换为Xbox 360 - 性能问题极大

7
我想把我的电脑游戏转换成Xbox 360的版本。在电脑上运行得非常好,CPU是Intel Core 2 Quad @ 2.40Ghz,显卡是Radeon 4850 512MB。
我将它移植到了Xbox,但一开始导入列表时就出现了一些与不变性和继承相关的问题,所以我简单地使用了名为.Cast<>()的LINQ方法。
如果这个方法会带来很大的开销,请告诉我,因为由于某些原因,我无法在360上部署性能分析,很可能是因为它是在360上运行。
然后另一个问题出现了,那就是一个很好的System.OutOfMemoryException。我的天空盒纹理大小为4096x4096,将其减半后删除了该错误。奇怪的是,它们只有3MB x 6,因此不应该占用那么多可用的512MB。
当所有这些问题都被排除后,每秒只有1帧的流畅度被引入。一分钟后它崩溃了,显示"Code 4",不知道是什么意思。
它玩起来像幻灯片。下面是从电脑游戏中获取的一些性能分析图像。它们并不差。
CPU:http://i.imgur.com/JYx7Z.png RAM:http://i.imgur.com/C29KN.png,而72%等于150MB。
我希望这里有人有这个问题的经验。坦率地说,我非常愿意倾听。
1个回答

10

你的性能问题根本原因几乎肯定是因为你在游戏运行时(启动后,在Draw / Update循环期间)分配内存。

在 Windows 上,这没问题。Windows 上的垃圾收集器是分代式的(只在可能清理新对象),而且速度非常快。它也很聪明地选择运行的时间。

另一方面,Xbox 360上的垃圾收集器完全没用。它在每分配1MB内存时都会运行。它在运行时检查整个托管堆。而且启动速度相当慢。

因此,答案是永远不要在游戏运行状态下分配内存。

关于这个问题有一篇很好的博客文章 here. (它还描述了从不分配内存的替代方案——减少堆复杂性——这真的很难实现,我不建议这样做。)

  • 您将需要删除诸如LINQ之类的内容,因为它创建的查询对象是堆对象,它经常需要使用的委托也是堆对象。改用简单循环。
  • 如果在绘制/更新中分配了自己的引用类型,则必须在可能的情况下转换为使用值类型或添加对象池。
  • 创建string对象是内存分配的另一个常见来源——相反,您可以重复使用StringBuilder并直接呈现它。
  • 将事物(特别是数字)转换为字符串,即使对于StringBuilder也会分配内存。您需要编写/查找无需分配的替代方案。我对这个类似问题的答案int

诊断内存分配位置的最佳方法是在 Windows 上使用 CLR Profiler 运行游戏。这将告诉您内存何时以及在哪里被分配。只需进行优化,直到不再分配为止。

(或者直到每个关卡/地图/房间/其他可靠分配少于1MB,并在适当的停顿时间手动运行GC,比如静态加载屏幕或淡入淡出效果)

代码 4 是未处理的异常。 您需要安装一个顶级异常处理程序来输出消息,或在调试器中运行游戏以确定原因。

最后: 那可能是您纹理的压缩大小(使用 PNG 或 JPEG 或类似技术)。如果您的纹理是未压缩的,则 4096 × 4096 × 6 × 4 字节 = 384MB。这非常大 - 难怪您会遇到内存耗尽的问题。您可以使用 DXT1 进行压缩并使它们变小 6 倍 (说明维基百科)。您还可以降低它们的分辨率。而且,您真的需要底面吗?


1
非常感谢,在搜索很久后,我找到了类似于你的答案。当我运行我的CLR配置文件时,发现我每帧分配了约60MB的内存...这不好。这是因为我将游戏中所有可碰撞的物体添加到列表中,然后在每帧中将它们放入碰撞线程。我可以将其制作为静态列表,其中只是一个参考,这也许是我要做的,但这样就有可能出现碰撞延迟。但我想这是唯一的选择。 - user1146887

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接