0

I am currently using the book "Learning LibGdx Game Developement, Second Edition" as a reference book while programming and I stumbled over their implementation of an Asset Managing class. They implement it using a singleton pattern, something I don't really have allot of experience with. There will be only one instance of this Manager class throughout all screens and it will be disposed when the game is closed. So from my (rather inexperienced) pov I would agree with the author that a singleton makes sense, since this way I don't have to pass it over to every class I need it in. However I also heard that they got a bit of a bad reputation so I thought I would ask here. Does it make sense to use a singleton pattern for an Asset Managing class in LibGdx?

The_Blog
  • 155
  • 1
  • 12
  • Your book is doing dangerous stuff. I see AssetManager being used a lot as a static object but this is against advice in the documentation. Basically, when you background your app Android can dump the contents of the Singleton and you will end up with black images. https://github.com/libgdx/libgdx/wiki/Managing-your-assets#creating-an-assetmanager – Madmenyo Mar 30 '16 at 08:24
  • Actually, its not the content of the singleton that is being dumped, but the textures in video memory that the singleton keeps a link to. Still, the resulting black images is the same. – p.streef Mar 30 '16 at 13:06
  • @Menno Gouw I can see why a singleton is not the best idea with the answers given and I did change it back to a normal object that get's passed along. However the `AssetManager` object isn't static so there shouldn't really be any problem from that side, am I wrong? Kinda trying to get a better understanding, cause I did read the documentation and didn't make it static because of that. – The_Blog Mar 30 '16 at 17:43
  • If the `AssetManager` is not static you are fine. I always create a `Assets` class with static `AssetDescriptors` so I can use these when I want to grab assets from the manager. `myTexture = assetManager.get(Assets.MyStaticAssetDescriptor)`. This is both lifecycle safe, you cannot miss spell, you do not have to cast the assets into proper types and you get a nice list of your assets with intellisense. – Madmenyo Mar 30 '16 at 21:25
  • Thanks for the tip. :) However I am using a Texture Atlas which means I only get the Texture through `findRegion(String name)` or `createSprite(String name)` and since these methods are rather costly it is advised to cache them. So I can't really use AssetDescriptors. – The_Blog Mar 31 '16 at 04:19

3 Answers3

3

There are constantly people on here asking why their textures are corrupted and it always ends up being that they were trying to use static references or singletons for their assets. But f you understand how to make sure you're disposing of all disposables and always loading new instances when the game is reopened, then it should be fine.

Anything that implements Disposable must be disposed before it goes out of scope or the game closes. If you loaded something with AssetManager, then it is sufficient to dispose of just the AssetManager instance which will indirectly dispose of everything it loaded.

The dispose method of your top level ApplicationListener class is the guaranteed exit point of your app and you must ensure all disposables anywhere in your game are disposed by the end of this method.

And the create method means you have a new game instance so you should not try to reuse any static references to Disposables at this point.

The reason many people have issues with this is that a singleton is often lazy loaded so the first time the game is reloaded, the asset manager instance is not recreated (because Android Applications often stay alive even if the game Activity has exited, and so static references live on).

Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • First of all thanks for the extensive answer. :) I am currently disposing the `AssetManager` inside the `dispose()` method of my main Game class. I also use [eager initialization](https://en.wikipedia.org/wiki/Singleton_pattern#Eager_initialization) so the instance is recreated every time the game get's started. So unless I am mistaken that should be okay. – The_Blog Mar 29 '16 at 22:57
  • @The_Blog you are mistaken and will most likely have to redesign your asset handling in the future. There is really nothing wrong with a regular `AssetManager` object and pass it to whoever needs it. You can use `AssetDescriptors` as `static` in your `Asset` class so you can easily lookup and get Assets from the `AssetManager` you are passing along. There are a lot of online resources that teach you wrong but I find it very odd that a book is teaching you this. – Madmenyo Mar 30 '16 at 08:31
  • Note that eager initialization is also an example of *not* properly managing `static` variables. – Xoppa Mar 30 '16 at 08:36
  • Thanks for your input, I'm gonna change it back and just pass it as a normal object. I am still pretty new to using libGdx. – The_Blog Mar 30 '16 at 16:13
2

If you are learning libGDX game development then using a singleton (or otherwise static resources) is something that you really really should avoid.

If you don't properly manage and understand the life-cycle of static variables (lazy initialization as typical used with singletons is a good example of not properly managing them) then you might end up using resources which are no longer valid or have a value which you might not expect. This is because the statics might outlive your application. Of course you can work around that, but that are problems which you really don't want to deal with while learning.

But even more important, it is a good indication of a bad structure (Object Oriented Design). You should not need to have access to resources in that many classes to justify a singleton. You typically only need access to resources in e.g. your Screen implementation.

Xoppa
  • 7,983
  • 1
  • 23
  • 34
0

A static field alone like

public class YourGameClass implements ApplicationListener
{
    public static AssetManager assetMgr;
}

would be much simpler and easier. Just assign it whenever your game is ready (like in create method), and reference it by YourGameClass.assetMgr. When your application is about to die (like in dispose) – dispose it.

Simple. Since you have only one instance of YourGameClass, you would have no troubles with that.

Tenfour04
  • 83,111
  • 11
  • 94
  • 154
desertkun
  • 1,027
  • 10
  • 19