Proper way to unload resources when switching game states?

Oct 21, 2011 at 2:38 PM

I have a menu system gamestate with a SunburnLayer for displaying some 3d objects. When I select a menu option to enter the game, and new gamestate is loaded with its own SunburnLayer for actual game play. If I just simply switch gamestates using


.Instance.LoadGameState(new ArcadeGameState(Application.Instance, sceneFileName));

When the SunburnLayer in the ArcadeGameState runs it's LoadContent method it errors with the following error:

Content repository named 'Content' already exists.

SynapseGaming.LightingSystem.Core.ContentRepository.(ContentRepository )
   at SynapseGaming.LightingSystem.Core.ContentRepository..ctor(String , ContentManager )
   at SynapseGaming.LightingSystem.Processors.ContentRepositoryReader_Pro.Read(ContentReader input, ContentRepository instance)
   at Microsoft.Xna.Framework.Content.ContentReader.InvokeReader[T](ContentTypeReader reader, Object existingInstance)
   at Microsoft.Xna.Framework.Content.ContentReader.ReadObjectInternal[T](Object existingInstance)
   at Microsoft.Xna.Framework.Content.ContentReader.ReadObject[T]()
   at Microsoft.Xna.Framework.Content.ContentReader.ReadAsset[T]()
   at Microsoft.Xna.Framework.Content.ContentManager.ReadAsset[T](String assetName, Action`1 recordDisposableObject)
   at Microsoft.Xna.Framework.Content.ContentManager.Load[T](String assetName)
   at Indiefreaks.Xna.Rendering.SunBurnLayer.LoadContent(IContentCatalogue catalogue, ContentManager manager) in C:\Perforce\ImaginEngine\AXE\Code\WP7\Axeman\Indiefreaks.Game.Framework\Rendering\SunBurnLayer.cs:line 70

So obviously I am missing some clean up code somewhere. Any direction you can give me would be greatly appreciated.

Oct 21, 2011 at 10:29 PM

Hi, I need to get a bit deeper on this topic but I guess I know what you need to do.

Each SunBurnLayer has a Repository property of type ContentRepository. If you create it using the full constructor signature, you'll ask IGF to load a new Scene using the ContentRepository loaded from the path provided in the constructor.

If you want to reuse the same ContentRepository, you'll need to call Repository.Dispose() when you unload/dispose the previous SunBurnLayer in use.

If it works out, I'll see to implement an automated feature in IGF to manage these cases.


Oct 22, 2011 at 11:33 AM
Edited Oct 22, 2011 at 11:46 AM

Not sure if this is the same problem, but I had something similar happen too when using Application.Instance. Turns out that when I selected the menu option, it tried to start the next gamestate every update, so it would create the Content Repository, and then try making another one, causing the above error (or one very similar).

Simple workaround was to have a class level bool _HasClickedMenuItem = false to stop it calling every Update cycle.

Then wrap your LoadGameState call in an if statement:


if (!_HasClickedMenuItem)
       _HasClickedMenuItem = true;
       Application.Instance.LoadGameState(new ArcadeGameState(....));


Didn't do much testing to see if this causes any problems further down the line, but it seemed to be a quick fix. Hope this helps!

Oct 27, 2011 at 1:30 AM

I have the same problem :

I have created my own global content manager to fix this issue like a classic XNA project.

Oct 27, 2011 at 10:51 AM

I'll try to implement something in the SunBurnLayer so that it's easier for developers to dispose correctly an entire Scene and its ContentRepository on v0.9.0.0


Nov 23, 2011 at 2:50 PM

I am still somewhat at a loss for this issue. I implemented dispose calls for the Repository prior to calling load game state and still receive the same error with one caveat. The error no longer happens every time, it now is on occasion. This leads me to beleive that there is some sort of timing issue with the threading. Maybe the repo is not disposing fast enough and loading the new game state is occuring before the Content repo is removed.

@x35mm - Definately not an issue where its trying to load every update, but thanks for your input.

@rc183 - Would you be willing to share your implementation?