I am managing my assets using Assets class which has assetManager
In game screens(eg. SplashScreen or MenuScreen) I am loading assets which I will use in this screen using assetManager.load() and when game setScreen to another screen I call dispose() of the previous one ?
Should I call assetManager.clear() in dispose() of screen ?
Or calling it in dispose of my game class (which I use right now) ?
something like this :
public class GameMain extends Game {
#Override
public void dispose(){
super.dispose();
Assets.dispose();
}
}
Sounds like you'll want to call it at the screen level. Calling clear on the asset manager will dispose ALL assets the manager knows about. So each screen will have to load all the assets it needs to use, as the manager is effectively cleared each screen.
If you dispose your assets at the game level like you do now, sounds like you may have a lot of extra assets loaded that you don't need and could affect performance (ie, your menu assets are still loaded when you're showing your play screen) .
If you have assets you share between screens, keep that in mind. Calling clear at the screen level will have you reloading those assets every screen switch - which may be just fine depening on the amount/size of your assets.
Related
In libgdx, screen.setScreen() doesn't call dispose automatically right. Inside a overridden setScreen, do I have to call screen.dispose first and then call super.setScreen or call the later first?
I know this may seem like duplicate question but still I wanted to know because super.setScreen calls screen.hide. Is calling hide after dispose run-time safe?
Is it a bad practice?
I am making a 3D game based on this and this example .
Here I am extending GameName class by Game and trying to override setScreen so as to call dispose if screen is not null and then call super.setScreen .
screen.dispose() is never called by LibGDX. You must do it manually yourself before dropping the reference to your screen. If you don't plan to reuse the Screen instance, having screen.hide() call screen.dispose() is the perfect place to do it.
screen.hide() is never called in response to Android events.
I don't recommend overriding game.setScreen() to dispose of screens unless you know for sure you never want to reuse any screen instances. In most simple games, you do want to reuse them rather than waste time unloading and reloading assets repeatedly.
Two type of disposable assets(SpriteBatch, Texture, Stage, ...), one is shared on different screen and another one is specific for particular screen.
Shared Assets should be disposed from Game's dispose() method.
Screen specific assets should be disposed through dispose() method of Screen but screen's dispose() never called so you need to call it explicitly.
When you change your screen hide() method of Screen called so you should call dispose() method from hide() method.
I programmed a game made of multiple screens and every time I need a new screen I use the code
dispose();
game.setScreen(new GameScreen(game));
Inside the dispose method I called the dispose method of each asset like Textures and so on.
I also use the asset manager to load the assets required for the game play screen. In that case when I close the game play screen I also call AssetManager.clear().
Now when I start the game I only have the menu screen and the used memory is about 20MB, then in the game play screen I reach 212MB and when I come back to the menu screen, after disposing the AssetManger, I still have 186MB.
The main problem is that if I start a new game play screen the memory reaches 320MB so after some game play screens the game reaches 700MB!
What's wrong with my code?
You should never have to manually call your Game class's dispose() method. It's called automatically upon changing screens or closing the app. Instead, you should override the Game dispose() like this (code taken from a project I'm working on):
#Override
public void dispose()
{
super.dispose();
assets.dispose();
}
The assets object is my AssetManager. Upon closing the app, I want all my loaded textures to be destroyed from memory. I can't promise anything, but I'm pretty sure that's your problem.
I have this wierd situation that i can't understand.
I developed an application on android studio, on the first activity i start a second activity, on that second activity i created a SurfaceView child class that extends surfaceView and implemment Runnable and draw on the canvas inside run(), when i exit the thread i call onRestart() to start the canvas thread again.
all good so far, i open the thread, draw some images in a loop, exit the thread loop, restart.
the problem is that after 20 times of restarting, the application crash with no logical reason.
what do you think the problem can be? how to check it and fix it?
this function is the thread work inside the surfaceView child class (of the activity)
#Override
public void run() {
while (!_susspendThread) {
// draw images
}
onRestart();
}
this function is on the parent activity class
protected void onRestart() {
// make some changes, nothing critical to the question
// examp. count++;
surface_view.StartThreadWork();
}
another thing i must say although i dont belive it's related to the problem is that onCreate i read some internal files.
thanks for any help.
You have a memory leak, and this could be from many things. A good place to begin, is to use the onDestroy() methods of your Activities to cleanup any resources you have generated (like the internal files you are creating in your onCreate method).
Also, there are tons of tools for tracking memory usage, in AndroidStudio (AS) there is a "Memory" tab in the "Android" view. Also, you can run the "Monitor" tool (available from the command-line, or within AS to get ton's of details on what type of resource you are leaking.
Let's say I have a screen A with Skin that was loaded in memory by asset manager:
private Skin skin;
...
skin = (Skin)MyGame.ResourceManager.getAsset(AssetEnum.UISkin);
//UISkin("Menu/UISkin.json", Skin.class),
I need to load the next screen B that also refers to AssetEnum.UISkin. The simple way is
dispose screen A
unload resources of screen A
load resources of screen B
initialize screen B
But I want to show some loading wheel on the screen A while resources of screen B are still loading. With this extension steps look like
load resources of screen B
initialise and set screen B
dispose screen A
unload resources of screen A
The problem is when I call dispose on third step, skin.dispose() removes texture of previous screen that I also need on current. And this situation appears every time when "dispose screen A" is after "load resources of screen B". Does anyone have any suggestions? Please help
You can create a separate static class that loads your assets and keep it until you don't need it anymore.
Lets call this class AssetLoader.
I assume that you know how java works and how libgdx works.
Within the class, AssetLoader, you create 2 methods
Public static void load() {}
and
Public static void dispose() {}
Also declare your skin as a static member
Public static Skin skin;
Within your load() method do the loading of your skin, and within your dispose() method you write your disposal method.
When your want to want to load your assets, call
AssetLoader.load();
the methods are all static you don't need to initialize AssetLoader in your entire code. Just call it.
When you want to use the skin (for example, your Screen1() method)
UISkin("Menu/UISkin.json", AsssetLoader.Skin.class);
Finally when your game ends, you call
Assetoader.dispose();
You can literally put anything in the AssetLoader that is static. Such as textures and soundtracks. The benefit is that you only need to call the load() method once in your entire code and you can use it for the entire duration of your game. Just remember to dispose it when you don't need it anymore.
EDIT: Another thing you can do is to use AssetManager
More details here
What is the proper way of completely disposing of a screen in Libgdx? Currently If I click where a button was on my previous screen the button still does what it would of done if I were on that screen. Should I be .dispose()-ing everything I can in the dispose() method? or is there a simpler way to dispose of everything on screen?
Unfortunately there is no easier way. These classes do not share any kind of common "Disposable" interface, or anything like that, to do it automatically. Everything that has a dispose() method needs to be disposed manually when it's not needed anymore.
This is also valid for the Screens themselves. When switching Screens they do not get disposed automatically, but you need to do that yourself (before calling Game.setScreen()).
On the other hand, this is not a big deal. Just look through everything in your Screen and check whether it has to be disposed or not. If there is a dispose method, call it in dispose() of the Screen.
BUT this does not explain your behaviour about invisible buttons from the last Screen. I suppose you use a Stage and used Gdx.input.setInputProcessor(stage);. This setting will not be changed when you change the screen and you have to set the input processor to the Stage of your current Screen, or to whatever that handles the input in your current Screen. That way the "old" stage will not catch any inputs anymore.
I can confirm that this issue is not passing the inpur processor a new stage. this will result in "ghost" buttons as described.
Unfortunately LibGDX API documentation says
Note that dispose() is not called automatically.
So what I do is disposing all disposables (such as Stage, Skin, Texture ... etc) inside the hide() method in the Screen because hide() is called automatically and it works very well!
example:
public class GameScreen implements Screen {
...
#Override
public void hide() {
mainStage.dispose();
playGroundStage.dispose();
controller.dispose();
labelActor.dispose();
}
...
}