3
\$\begingroup\$

When I make games, I generally create a static class called Art that has static fields to track all content in the game. For example

public static class Art
{
    public static SpriteFont defaultFont;

    public static Texture2D playerSprite;

    public static void LoadContent(ContentManager content)
    {
        defaultFont = content.Load<SpriteFont>("Fonts/DefaultFont");
        playerSprite = content.Load<PlayerSprite>("Sprites/PlayerSprite");
    }
}

My question is do these objects in my art class take up memory for the duration of the games lifetime? The point of this class is to only have to load my art once in the game and have easy access to the assets anywhere in my project, but at what cost?

\$\endgroup\$
  • \$\begingroup\$ Yes, it will remain in memory during the entire lifetime of your game. There is nothing wrong with doing it this way. \$\endgroup\$ – jgallant Apr 29 '16 at 11:01
2
\$\begingroup\$

When LoadContent works as advertised, then it seems to load all resources from disk into memory.

The result will be a longer load-time at the beginning of the game, but far shorter load-times during playing. Whether or not this is a good tradeoff depends on how the players play your game. When it's a game you play for hours in one session, players would certainly prefer shorter ingame loading times. When it's a game you just play for a few minutes, players whould rather prefer a fast startup.

Having everything in memory at once could cause you to run out of RAM. Whether or not this will happen depends on how large your assets are (note that filesize does not necessarily correspond with memory requirement after loading) and how much RAM your target platform usually has.

An alternative would be "lazy loading". Instead of loading all assets at startup, you load resources when they are first requested. You would usually do that by calling a function to obtain an asset. This could look something like this:

public static class Art
{
    private static HashMap<String, Sprite> spriteCache = new HashMap<String, Sprite>();

    public static Sprite getSprite(filename) {
        // look in sprite cache if sprite was already loaded before
        Sprite sprite = spriteCache[filename];
        if (sprite == null) {
              // sprite wasn't found. load it now.
              sprite = content.Load(filename);
              spriteCache[filename] = sprite;
        }
        return sprite;
    }
}

Warning: This implementation is not thread-safe. It will load the same resource multiple times in parallel when requested by multiple threads at once

The upside is that you won't have any loading screens at all, because nothing gets preloaded. The downside is that the game will start to lag whenever a lot of unloaded stuff appears in the game for the first time. When your game needs almost all assets on startup, then you will end up with the same loading time as before.

You will also end up with the same memory usage as before when the player plays for a long time and sees every art asset you have. To prevent this "memory leak" effect your Art class could keep track of the time each asset was requested last and automatically unload those which were not requested for a while. When you go down that route, make sure that every use of an asset goes through your Art class and no other class keeps own references to assets. Otherwise the Art class could think an asset is no longer used even though something uses it all the time but does so through a reference it owns itself.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.