Memory XNA内存中加载的纹理太多

Memory XNA内存中加载的纹理太多,memory,xna,loading,textures,Memory,Xna,Loading,Textures,我正在为图形引擎开发一个级别编辑器。最近,随着一个项目的扩展,我遇到了内存问题。特别是,级别相当大,需要加载大约300个大小不同的纹理。一些纹理非常大,如2048x2048,其他纹理较小,如256x256或512x512。无论如何,编辑器在这个级别上消耗了1.3gb的内存,一些纹理无法加载,因为它抛出了内存不足的异常。那么我这里有什么解决方案呢 现在我能想到的唯一解决方案是将关卡分成更小的部分,并根据需要加载纹理,具体取决于可见区域。但我相信这会大大降低在场景中导航时的性能。有什么想法吗?在这个

我正在为图形引擎开发一个级别编辑器。最近,随着一个项目的扩展,我遇到了内存问题。特别是,级别相当大,需要加载大约300个大小不同的纹理。一些纹理非常大,如2048x2048,其他纹理较小,如256x256或512x512。无论如何,编辑器在这个级别上消耗了1.3gb的内存,一些纹理无法加载,因为它抛出了内存不足的异常。那么我这里有什么解决方案呢


现在我能想到的唯一解决方案是将关卡分成更小的部分,并根据需要加载纹理,具体取决于可见区域。但我相信这会大大降低在场景中导航时的性能。有什么想法吗?在这个问题上,应该有一些标准的级别编辑器方法。

您基本上有两个选择

切换到基于平铺的方法。如果您使用的是瓷砖,这意味着您可以反复使用相同的纹理,从而节省大量内存。 如您所述,切换到按需模式。 我在想,如果你的艺术方向与基于瓷砖的方法不匹配,那么你应该开始考虑方法2。要考虑的几件事

它不一定要慢,只要你的活动区域足够大,这样你就不会因为加载太频繁而重击磁盘,你就应该没事了。 衡量一下,你可能必须更好地掌握你的记忆预算,并围绕它设计你的水平,而不是设计直到你撞到墙为止- 维护单独的内容管理器,请记住,您不能卸载通过contentmanager加载的单个内容,因此请保留一个管理器列表,以便在移动时可以交换。
你基本上有两个选择

切换到基于平铺的方法。如果您使用的是瓷砖,这意味着您可以反复使用相同的纹理,从而节省大量内存。 如您所述,切换到按需模式。 我在想,如果你的艺术方向与基于瓷砖的方法不匹配,那么你应该开始考虑方法2。要考虑的几件事

它不一定要慢,只要你的活动区域足够大,这样你就不会因为加载太频繁而重击磁盘,你就应该没事了。 衡量一下,你可能必须更好地掌握你的记忆预算,并围绕它设计你的水平,而不是设计直到你撞到墙为止- 维护单独的内容管理器,请记住,您不能卸载通过contentmanager加载的单个内容,因此请保留一个管理器列表,以便在移动时可以交换。
使用不同质量的纹理可能是一个好主意,如果您离使用64x64纹理很远,那么当您靠近时,继续将其换成128x128、256x256、512x512等。。。另外,请重新考虑使用2056x2056的纹理,因为最好使用4个1024x1024纹理:

注意:生成mip映射部分地执行此操作,但不会释放计算机上的内存


编辑:同时尝试启用DXT5纹理压缩,这可能会节省大量内存

使用不同质量的纹理可能是一个好主意,如果您远离使用64x64纹理,那么当您靠近时,继续将其换成128x128、256x256、512x512等。。。另外,请重新考虑使用2056x2056的纹理,因为最好使用4个1024x1024纹理:

注意:生成mip映射部分地执行此操作,但不会释放计算机上的内存


编辑:同时尝试启用DXT5纹理压缩,这可能会节省大量内存

首先,谢谢你的回答。现在,虽然我不熟悉基于瓷砖的方法,但一个纹理可以被多个对象使用。对于使用它的每个对象,它不会在内存中多次加载。我想指出,纹理保存在字典中。我不使用内容管理器,而是使用Texture2D.FromFile加载纹理。我可以试试那种随需应变的方法。使用内容管理器会节省内存吗?我想不会,所以我应该坚持使用已经实现的方法。我只负责工具,测量是由其他人完成的:哦,我明白了。。。内容管理器实际上只用于运行时代码,用于通过内容管道运行的纹理。我想你的意思是当你试着运行游戏时,你的内存已经用完了。但你描述的机制是同一个概念。。。存储对纹理的引用,并在移动时加载/卸载。但请记住分批进行,分批大小略大于屏幕,这样,如果用户进行小动作,就不必不断加载/重新加载。看看谷歌/必应地图在地图上移动时如何加载纹理。。。你会想模仿这个是的,我想这应该是我的目标,模仿谷歌地图一样的行为。在加载级别时抛出内存不足异常,并且
埃默里的消费正在增长。无论如何,我会尝试随需应变的方法,因为它似乎是唯一的解决方案。谢谢:不过我有个问题。如果用户缩小并且整个场景可见,那么将加载所有纹理,这将再次抛出异常:首先,感谢您的回答。现在,虽然我不熟悉基于瓷砖的方法,但一个纹理可以被多个对象使用。对于使用它的每个对象,它不会在内存中多次加载。我想指出,纹理保存在字典中。我不使用内容管理器,而是使用Texture2D.FromFile加载纹理。我可以试试那种随需应变的方法。使用内容管理器会节省内存吗?我想不会,所以我应该坚持使用已经实现的方法。我只负责工具,测量是由其他人完成的:哦,我明白了。。。内容管理器实际上只用于运行时代码,用于通过内容管道运行的纹理。我想你的意思是当你试着运行游戏时,你的内存已经用完了。但你描述的机制是同一个概念。。。存储对纹理的引用,并在移动时加载/卸载。但请记住分批进行,分批大小略大于屏幕,这样,如果用户进行小动作,就不必不断加载/重新加载。看看谷歌/必应地图在地图上移动时如何加载纹理。。。你会想模仿这个是的,我想这应该是我的目标,模仿谷歌地图一样的行为。在加载级别和内存消耗增长时引发内存不足异常。无论如何,我会尝试随需应变的方法,因为它似乎是唯一的解决方案。谢谢:不过我有个问题。如果用户缩小并且整个场景可见,那么将加载所有纹理,这将再次引发异常:基本上,使用DXT5压缩是解决方案,而不是按需加载,至少直到级别变得更大。内存消耗从1.3gb降至300-400mb。相当大的性能提升!至于纹理大小,有些纹理需要较大,例如纹理图集或常规动画中使用的纹理。虽然我可以更改代码以支持来自多个源的动画,但我不能要求引擎程序员在引擎中执行相同的操作;我正在为EngineBasical开发一个编辑器。事实证明,使用DXT5压缩是解决方案,而不是按需加载,至少在级别变得更大之前是这样。内存消耗从1.3gb降至300-400mb。相当大的性能提升!至于纹理大小,有些纹理需要较大,例如纹理图集或常规动画中使用的纹理。虽然我可以更改代码以支持来自多个源的动画,但我不能要求引擎程序员在引擎中执行相同的操作;我正在为引擎开发一个编辑器