1
\$\begingroup\$

I am currently programming a space shooter with MonoGame. I encountered an issue where the memory usage constantly increases when I load a specific class. This class is called Background which generates a background image for the game. It does so by layering different images on top of each other, which creates a nice looking solar system with random planets, asteroids and moons. The textures I use sum up to a total of 100Mb.

I load everything in the beginning of the game via:

content.Load<>();

The ContentManager is then passed around by the screen manager class. To check the generation of the background image I use this code:

if(InputManager.KeyPressed(Keys.R))
{
    background.LoadContent(content);
}

This generates a new background every time I press R; every time I press R the memory usage increases by 30-50Mb. I can't understand why this is happening. I loaded everything in the beginning so the ContentManager should give me a reference to the already-loaded objects and not load them again.

I don't create a new background I just take the already existing background and load it again, which means that it shouldn't allocate any new memory. It should use the already existing variables and store other textures in there. I already tried unloading everything via: background.Unload() that didn't help. Also unloading everything with Content.Unload() did not help. The last thing I tried was periodically calling GC.Collect(), but that didn't help either.

Why is this happening?

Edit:

I wrote every class myself. Here is a short explanation of the Background class:

public void LoadContent(ContentManager content)
{
rnd = new Random();

//Initializing Containers

background = new List<Image>();
planetLayer = new List<Image>();
celestialBodys = new List<Image>();
rockLayer = new List<Image>();
nebula = new List<Image>();

int numberOfAsteroids = rnd.Next(2, 6);
for (int i = 0; i < numberOfAsteroids; i++)
{
    asteroidNumber = rnd.Next(1, 10);
    asteroidTexture = content.Load<Texture2D>("Texture\\asteroid_" + asteroidNumber.ToString(fmt));
    asteroidImage = new Image(asteroidTexture, new Vector2(rnd.Next(0, (int)Globals.gameDimension.X), rnd.Next(0, (int)Globals.gameDimension.Y)));
    asteroidImage.scale.X = (moonImage.texture.Width * moonImage.scale.X) * 0.5f / asteroidTexture.Width;
    asteroidImage.scale.Y = (moonImage.texture.Height * moonImage.scale.Y) * 0.5f / asteroidTexture.Height;
    rockLayer.Add(asteroidImage);
}

It doesn't inherit anything. It first creates a few Lists where all the images that should be drawn are stored. In the next step it creates a random number wich represents the number of Asteroids. For every Asteroid it creates a new random number wich is then loaded as texture. If its a 3 it loads content.Load<Texture2D>("Texture\\asteroid_003"). Then it creates a new Image at a random Location. Scales it properly to the current Screensize and adds it to a Layer. This whole process is also done with the Planet, the Fog and Nebulas, but its always the same process.

After Searching for a long time I think this could be the Problem:

     renderTarget = new RenderTarget2D(graphicDevice, (int)dimension.X, (int)dimension.Y);
        graphicDevice.SetRenderTarget(renderTarget);
        graphicDevice.Clear(Color.Transparent);
        spriteBatch.Begin();
        if(texture != null)
        {
            spriteBatch.Draw(texture, Vector2.Zero, Color.White);
        }
        if(text != String.Empty)
        {
            spriteBatch.DrawString(font, text, Vector2.Zero, Color.White);
        }         
        spriteBatch.End();
        texture = renderTarget;
        graphicDevice.SetRenderTarget(null);

The background class creates a new Image and gets the Texture from the Contentmanager wich is always the same Image and should not take up any more memory. After that it creates a rendertarget and renders it. Then it stores it to the old variable. I think this is the Problem, because it creates a new Texture every time the Image class loads a texture and so it has to store all the diffrent rendered images.

\$\endgroup\$
  • \$\begingroup\$ Please ask only one question per post; you've got three here that are very different. I'd edited away all but the first; you can re-post the others as separate questions if you like. \$\endgroup\$ – Josh Jul 14 '16 at 17:02
  • 1
    \$\begingroup\$ What does the Background class look like (what class does it inherit from)? In particular what does LoadContent do? Did you write it yourself? \$\endgroup\$ – Josh Jul 14 '16 at 17:06
  • \$\begingroup\$ According to the docs, ContentManager caches assets. Have you confirmed that calling ContentManager.Load() a second time returns a different object? \$\endgroup\$ – milk Jul 14 '16 at 21:38
  • \$\begingroup\$ Try to change this line: asteroidTexture = content.Load<Texture2D>("Texture\\asteroid_" + asteroidNumber.ToString(fmt)); to always load the same image (just put single string in). Not 100% sure but maybe you string concatenation messes with the ContentManager caching \$\endgroup\$ – floAr Jul 15 '16 at 7:54
  • \$\begingroup\$ I tried it but sadly it didn't help. I changed every string in the background class to a constant string. I still get a plus of 30 to 50 Mb on the ram if i reload the class. \$\endgroup\$ – Jonny Jamal Jul 18 '16 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.