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オブジェクトを持つゲームオブジェクトのリストを保持するようにプログラムを書き直しました。リストを確認したら、前のリストアイテムのテクスチャオブジェクトを破棄し、次のリストアイテムのテクスチャをそのテクスチャオブジェクトにロードします。リストはゲーム全体で1回だけトラバースされ、定期的に次のテクスチャセットに移動し、ロードするテクスチャを2つだけ選択するので、理論的には常にメモリに2つのテクスチャしか必要ありません。 。私はまだメモリエラーに遭遇しました。タイムリーにメモリからテクスチャを解放するためにdisposeメソッドにまったく頼ることができないかのようです。

ロードしているテクスチャはどれも125KBを超えていません。これは、WindowsPhone7用に作成しています。

不要になったテクスチャを削除するための最良の方法は何ですか?コードを参照すると、代わりに新しいtexture2dオブジェクトを作成し、それらを交換して、元のオブジェクトを破棄する必要がありますか?

4

1 に答える 1

8

OK、最初に少し背景を説明しContentManagerます。ロードされたオブジェクトをキャッシュします。ここ(またはここ)に、より詳細な説明があります。しかし、基本的には、それぞれがロードするすべてのものをContentManager 所有しています。Disposeそのコンテンツを呼び出すべきではありません。ContentManager.Unloadそれをクリーンアップする唯一の方法は、 (または)を使用してキャッシュ内のすべてをアンロードすることDisposeです。

あなたが抱えている問題は、Load以前に呼び出したテクスチャを試した後、その破棄されたDisposeテクスチャを使用しようとしていることだと思います。

ContentManagerはすべての(空の、破棄された)オブジェクトを格納しているため、メモリが不足する可能性もあると思いますがTexture2D、ガベージコレクタがそれらを再利用できません(この回答を参照)。

したがって、このルートをたどる場合は、のキャッシュポリシーを変更する必要がありますContentManagerこれを行う方法は、このブログ投稿で説明されています。ただし、基本的には、コンテンツファイルからアセットの新しいインスタンスを作成するときに、から継承しContentManager、オーバーライドLoadし、呼び出します。ReadAsset

最も簡単な方法は、キャッシュを完全に無効にすることです。そのブログ投稿には、まさにその例があります。次に、コンテンツマネージャがロードするすべてのライフタイムを手動で管理するだけです(つまりDispose、自分で呼び出す)。

もう少し洗練されたものが必要な場合は、GameDevサイトで、この回答で提案しているデザインをご覧ください。

于 2012-10-18T13:25:28.303 に答える