1
votes

I know you can unload all the content in a monogame project, but I am wondering if it is possible to unload a specific texture, for example, after a level.

I have a texture that I modify using .GetData and .SetData, and I reuse this texture in other levels as well as when the player dies, however when I use it in another repeated level, or when I restart the current level, the texture remains in its modified state, rather than its original. If I unload all of the content then the texture gets modified and resets at the start of the level, however I lose some of my other content.

So the real question is, can you unload a specific texture without unloading all of the content?

Any help would be appreciated :)

2
Have you considered trying to make a copy of the original texture rather that modifying it? That way you could just modify the copy and throw it away when you're done. - craftworkgames

2 Answers

2
votes

The problem with simply disposing objects is that there is not a way for other parts of your code to know whether an object has been disposed. ContentManager only provides the Unload() method, which unloads and disposes all resources, and you cannot simply create your own derived implementation because its internal list of disposable assets is private (not protected). If you implemented your own Unload(string asset) method, this private list would still hold a reference to your asset and then try to dispose it again when the ContentManager is disposed (disposing twice should work if it's implemented correctly by the resource class, but if nothing else, you are preventing GC to reclaim this memory).

The only way to implement a ContentManager.Unload(string assetName) method would therefore be to change the MonoGame source directly.

Common approach is slightly easier: simply use multiple ContentManager instances, i.e. a shared ContentManager instance in the Game class, and a separate private ContentManager instance in each GameScreen (or whatever you are using to organize your game), which is disposed whenever you switch scenes.

For async content loading, I have also implemented a custom async content manager for my apps, which queues the loading job on first access into a separate thread and returns null on subsequent calls until the resource is fully loaded.

-1
votes

To answer your question instead of disposing of the entire content manager, you can dispose the texture object itself.

Texture2D MyTexture = Content.Load<Texture2D>("Texture.png");

Your content manager ( "Content" ) now has this texture loaded.

MyTexture.Dispose();

By disposing the texture object rather than the entire content manager only the specified texture will be "disposed". Though the texture will only be unloaded, the reference in the content manager will not be removed.

As pointed out by craftworkgames the reference to the texture object will remain in the content manager which means it can't be reloaded using Content.Load<>().

I think the approach you're looking for is not disposing the texture but just overwriting it when a level resets. When the level resets you just call the Content.Load method on the same texture object again. This will load the default texture back in overwriting your modified one.