Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

proper handling of LibGDX AssetManager

Tags:

libgdx

So I am making a game in LibGDX where I am using the AssetManager to load all my assets. I'm just not sure which is the proper way to use it.

Currently I am loading all the games assets before the first screen. Then I clear the manager in the dispose method. But that means that I have a bunch of textures etc that I wont need for all the screens. Could that lead to memory leaks?

The other approach I have in mind is to only load the assets I need for each screen and then unload them in each screens hide() method.

So I was wondering which of these two methods is the best way to go, or if there is a better way to deal with this?

Thanks

like image 544
Johan Avatar asked Apr 12 '14 17:04

Johan


1 Answers

First: if you are developing on Android, hide() will be called every time the user answers their phone or switches to another app. That means you have to re-allocate resources in show(). For resource-intensive games, such as RPG's, this could result in an annoying black screen while the game is re-allocating graphics, etc. Not fun.

Second: be careful about optimizing your game early on. If you're getting an Out-of-Memory error, a few menu graphics you forgot to dispose probably aren't the bottleneck.

With those points out of the way, I have found that the easiest way to implement the asset loader is to have a separate Assets class, looking something like this:

public static AssetManager manager;
public static TextureAtlas myGraphics;
public static TextureAtlas myOtherGraphics;

public static void create() {
    manager = new AssetManager();
    load();
}

private static void load() {
    manager.load("mygraphics.pack", TextureAtlas.class);
    manager.load("myothergraphics.pack", TextureAtlas.class);
}

public static void done() {
    myGraphics = manager.get("mygraphics.pack", TextureAtlas.class);
    myOtherGraphics = manager.get("myothergraphics.pack", TextureAtlas.class);
}

public static void dispose() {
    manager.dispose();
}

Then, in your loading screen's render() method, all you have to do is call Assets.manager.update() -- if it returns true, call Assets.done(), and move on to your game.

There are a few benefits to this approach. First, it allows you to keep all of your asset-loading logic in one class. Second, if you ever have to manually dispose a resource, you can simply call Assets.myGraphics.dispose().

If you find that you have too much graphics data to load during startup (e.g. 10 MB of sprites on Android), you can also try breaking up your graphics data into discrete chunks. In my game, each sprite has a separate TextureAtlas, and each TextureAtlas is cached into an array when it is loaded.

Frequently-used sprites, such as the main character, are always kept in memory, while older sprites are unloaded over time. With this approach, instead of using 10 MB of memory on sprites, I am now using less than 0.5 MB.

like image 146
user3525774 Avatar answered Nov 04 '22 11:11

user3525774