在XNA中,处置不再需要的纹理的最佳方法是什么? [英] In XNA, what is the best method to dispose of textures I no longer need?

查看:75
本文介绍了在XNA中,处置不再需要的纹理的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始了一个项目,其概念是在整个游戏中不断重复使用相同的texture2d对象,并定期重新加载新纹理.随着时间的流逝,当我进入以下位置时,这被证明是一个坏主意:System.OutOfMemoryException

I started a project with the concept of reusing the same texture2d objects continuously throughout the game, reloading new textures periodically. Over time this proved a bad idea as I was running in to: System.OutOfMemoryException

    bool loadImages(string image)
    {
        System.Diagnostics.Debug.WriteLine("beginning loading textures " + image);

        try
        {
            //image_a = null;
            //image_o = null;

            //image_o.Dispose();
            //image_a.Dispose();

            image_o = Content.Load<Texture2D>("images/"+image);
            image_a = Content.Load<Texture2D>("images/" + image+"_a");


            return true;
        }
        catch 
        { 
            System.Diagnostics.Debug.WriteLine("cannot load textures " + image);         
            image_a.Dispose(); 
            image_o.Dispose(); 
        }

        return false; //make sure the caller loads the subsequent image
    }

我猜想XNA在每次加载新内容时都会保留过去的纹理,因此我重新编写了该程序,以保留一个游戏对象列表,每个游戏对象都有其自己的texture2d对象.浏览完列表后,我将处理上一个列表项的纹理对象,并将下一个列表项的纹理加载到其纹理对象.该列表在整个游戏中只会被遍历一次,只是会周期性地移至下一个纹理集,而且我只会挑选2个纹理来加载,因此理论上在任何时候都只需要在内存中存储2个纹理即可. .我仍然遇到内存错误.好像我根本不能依靠dispose方法及时从内存中释放纹理.

I guessed that XNA was holding on to the past textures with each new content load, so I rewrote the program to instead hold a list of game objects each with its own texture2d objects. Upon going through the list I would dispose of the previous list item's texture objects and load the next list item's textures to its texture objects. The list would only be traversed once over the entire game, just periodically would I move on to the next texture set, and I would only pick out 2 textures to load so in theory there should only ever be needed 2 textures in memory at all times. I still ran in to a memory error. It's as if I can't at all rely on the dispose method to release textures from memory in a timely manner.

我加载的所有纹理都没有超过125KB,我正在为Windows Phone 7构建此纹理

None of the textures I'm loading is over 125KB, I'm building this for windows phone 7

删除不再需要的纹理的最佳方法是什么?参考代码:我应该创建新的texture2d对象,交换它们并处理原始对象吗?

What is the best method to drop the textures I no longer need? Referring to the code: should I instead create new texture2d objects, swap them, and dispose of the originals?

推荐答案

好,首先了解一下背景: ContentManager缓存加载的对象.有更详细的描述此处).但是基本上每个ContentManager 拥有它加载的所有东西.您不应在该内容上调用Dispose.清除它的唯一方法是使用ContentManager.Unload(或Dispose)卸载缓存中的所有内容.

OK, first a bit of background: ContentManager caches loaded objects. There's a more detailed description here (or here). But basically each ContentManager owns everything it loads. You should not call Dispose on that content. The only way to clean it up is to unload everything in the cache with ContentManager.Unload (or Dispose).

我猜您遇到的问题是您尝试Load先前称为Dispose的纹理-然后尝试使用该已处置的纹理.

I'm guessing that the issue you're having is that you've tried to Load a texture that you've previously called Dispose on - and are then attempting to use that disposed texture.

尽管我想您也可能会用完内存,因为ContentManager将存储所有这些(空的,已处置的)Texture2D对象,从而阻止垃圾回收器回收它们(请参阅

Although I suppose you could also run out of memory because the ContentManager is storing all those (empty, disposed) Texture2D objects, preventing the garbage collector from reclaiming them (see this answer).

因此,如果您想走这条路线,则需要修改ContentManager的缓存策略. 此博客文章中介绍了如何执行此操作.但是基本上,您想从内容文件中创建资产的新实例时,继承自ContentManager,覆盖Load并调用ReadAsset.

So, if you want to go down this route, you need to modify the caching policy of ContentManager. How to do this is explained in this blog post. But basically you inherit from ContentManager, override Load, and call ReadAsset when you want to create a new instance of an asset from a content file.

最简单的方法是完全禁用缓存,而该博文中有一个确切的示例.然后,您可以简单地手动管理内容管理器加载的所有内容的生命周期(即:自己调用Dispose).

The simplest thing to do would be to disable caching entirely, and that blog post has an example of exactly that. Then you can simply manually manage the lifetime of everything that content manager loads (i.e.: call Dispose on it yourself).

如果您想要更复杂的东西,也许看看我在

If you want something a bit more sophisticated, perhaps look at the design I propose in this answer, over on the GameDev site.

这篇关于在XNA中,处置不再需要的纹理的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆