Have you ever test your XNA game and find out later that the memory usage is so high even if your game is such a simple 2d game?
For sure, just count for me too. To tackle the problem at hand, firstly you need to look closely at your memory usage and then your ContentManager object !
Try to run your game while you are looking at “Task Manager” on the left side (may be your right :) ). When you click on a button resulting in loading other resource, look closely at the memory usage. Then if you go back to the previous screen you have been for, look closely again at your memory usage.
Does the memory lower? If not, why it still keeps increasing?
This is an important to answer in order to begin the first step of solving the problem at hand !
We are the expert of loading the resouce right ? Just look at the following code.
Texture2D texture; Model model; ... texture = Content.Load<Texture2D>("mytexture"); model = Content.Load<Model>("mymodel"); ...
The code just says that we are going to load texture, and another model into memory. It’s all that simple which is enough to attract us to think that it’s no problem at all behind the scene !!
So what’s the problem anyway?
The root of increasing memory comes from this problem. We just loaded resource but never get rid of it whenever we don’t need them anymore. To apply the unload-whenever-possible scheme into the XNA game. We use Per-Screen Content Management.
Why Per-Screen Content Management?
I use this name because most of the games, i.e. simple 2d game, rely on the scene-by-scene basis. We usually move from this screen to another screen. Screen in this case is one screen consists of images, particles, other resource showing to your eyes. Thus one screen can be your mainmenu screen, option screen, worldmap screen, or even in-game screen for each of level.
By moving from one screen to another, the resource from previous screen may not be needed in the next loading screen. Thus that why we are risk to increase the memory unnecessary. Unloading unused resource in the right time will dramatically improve the overall performance for the system with low memory in-house.
ContentManager has a method named “Unload”. This method will be used to unload all resource loaded by it. Thus if we have multiple of ContentManager, says ContentManagerA, and ContentManagerB. ContentManagerA loaded 15 resource so far, and ContentManagerB loaded 10 resource so far. By unload the resource from ContentManagerA first before going to another screen in which ContentManagerB resided, then we could significantly lower the memory usage.
Look at the code below to get more idea.
public class ScreenA: Screen { ... ContentManager content; ... public override void PreInitialize() { texture = content.Load<Texture2D>(".."); model = content.Load<Model>(".."); sound = content.Load<SoundEffect>(".."); } public override void Unload() { content.Unload(); } }
That is a sample concept code for one of the screen i.e. ScreenA which responsible for 3 resource in its own screen. For other screens, there may be more resource to load.
Thus by moving from one to another screen, remember to Unload() the previous screen, and do the PreInitialize() for the next screen to load. And when you got back, just do the reverse.
Ha ha, we could lower the memory by this such a simple approach !! Horayyyy!
Anyway for the deeper look at the code on how to create a ContentManager in each screen, we will take a look at service provider of the Game class (provided as the beginning of creating new XNA game progject).
Let’s see the constructor method of the screen class.
... public Screen(IServiceProvider services) { content = new ContentManager(services); } ...
IServiceProvider is the interface implemented by those classes which want to be a service provider. For default, you may use Game.Services and sent it into Screen’s constructor method. But if you manage your own engine, you usually create your own service provider class implemented IServiceProvider interface, so just put that class instance into that constructor, then you’re done !!
Much speak without any result to confirm is not that good right ?
So I put my result from fixing my memory problem of my game (Just Master: The Journey To Junk Lord) to you all as follows.
The peak of memory usage in the old version is 110 MB, but after fixed it becomes no more than 70 MB ! It could reduce by about 37%.
Also in the in-game session, the peak memory consumed was 110 MB same as the first case, but for fixed version it becomes about 56-57 MB reducing by about 50 % Ohh, fantastic, I love content management now !!
Anyway this technique is just the beginning of the content management itself, lots to be learned.
Fix it now, and come back later for further talk. :)
Haxpor

Like











Bookmarked your blog. Thank you for sharing. Definitely worth the time away from my classwork.