2

我开始了一个项目,其概念是在整个游戏中不断重复使用相同的 texture2d 对象,并定期重新加载新的纹理。随着时间的推移,这被证明是一个坏主意,因为我遇到了: 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 方法及时从内存中释放纹理一样。

我正在加载的纹理都不超过 125KB,我正在为 windows phone 7 构建它

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

4

1 回答 1

8

好的,首先是背景知识:ContentManager缓存加载的对象。这里(或这里)有更详细的描述。但基本上每个人都ContentManager 拥有它加载的一切。您不应该调用Dispose该内容。清理它的唯一方法是使用ContentManager.Unload(或Dispose)卸载缓存中的所有内容。

我猜您遇到的问题是您尝试Load使用之前调用过的纹理Dispose- 然后尝试使用该已处理的纹理。

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

所以,如果你想走这条路,你需要修改ContentManager. 此博客文章中解释了如何执行此操作。但基本上,当您想从内容文件创建资产的新实例时,您继承自ContentManager、覆盖Load和调用。ReadAsset

最简单的做法是完全禁用缓存,那篇博文就有一个例子。然后您可以简单地手动管理内容管理器加载的所有内容的生命周期(即:Dispose自己调用它)。

如果您想要一些更复杂的东西,也许可以看看我在这个答案中提出的设计,在 GameDev 网站上。

于 2012-10-18T13:25:28.303 回答