Java 内存泄漏。不断上升直到游戏崩溃
我是android开发的新手,我的游戏内存有问题。它不断上升直到崩溃。如果你能帮助我,我将不胜感激。多谢各位 另外,关于Spritebatch,我需要在java类中调用this.dispose吗?在java类中,我将其扩展到game,以便对其进行处理?如果是的话,我在哪里可以叫它?多谢各位Java 内存泄漏。不断上升直到游戏崩溃,java,android,libgdx,Java,Android,Libgdx,我是android开发的新手,我的游戏内存有问题。它不断上升直到崩溃。如果你能帮助我,我将不胜感激。多谢各位 另外,关于Spritebatch,我需要在java类中调用this.dispose吗?在java类中,我将其扩展到game,以便对其进行处理?如果是的话,我在哪里可以叫它?多谢各位 public class Zero implements Screen, InputProcessor { Pmacgame game; private Stage stage; pr
public class Zero implements Screen, InputProcessor {
Pmacgame game;
private Stage stage;
private Skin skin;
private Sound sound ,laser;
private Music musicbg;
private Sprite spritebg, playerImage;
private ImageButton imgbtnLeft, imgbtnRight, fire, color1, color2, color3, color4,
bullet1, bullet2, bullet3, bullet4;
public static final float fireDelay = 0.3f;
String rr2;
private static int o = 0;
Rectangle player;
ArrayList<Bullet> bullets;
ArrayList<Target> targets;
ArrayList<Explode> explodes;
//long lastDrop;
int score;
boolean a, b;
public static final float minSpawnTime = 0.5f;
public static final float maxSpawnTime = 1.25f;
float shootTimer, targetSpawnTimer;
Random random;
public static int select;
public static int dis = 0;
public float health = 1;
private Sprite greenBar, redBar, blueBar, pinkBar, greenBarO, redBarO, blueBarO, pinkBarO;
public Zero(Pmacgame game){
@Override
public void render(float delta) {
shootTimer += Gdx.graphics.getDeltaTime();
ArrayList<Bullet> bulletsToRemove = new ArrayList<>();
if (fire.isPressed() && shootTimer >= fireDelay) {
shootTimer = 0;
bullets.add(new Bullet(player.x + 32f));
}
for (Bullet bullet : bullets) {
bullet.update(Gdx.graphics.getDeltaTime());
if (bullet.remove)
bulletsToRemove.add(bullet);
}
targetSpawnTimer -= Gdx.graphics.getDeltaTime();
if (targetSpawnTimer<=0){
targetSpawnTimer = random.nextFloat() * (maxSpawnTime -minSpawnTime) + minSpawnTime;
targets.add(new Target(MathUtils.random(267, Gdx.graphics.getWidth()-350f)));
}
ArrayList<Target> targetsToRemove = new ArrayList<>();
for (Target target: targets){
target.update(delta);
if (target.remove)
targetsToRemove.add(target);
if (target.getY()<=0){
health -= 0.1f;
if (health<=0){
select = 0;
dis = 1;
this.dispose();
game.setScreen(new GameOverScreen(game, score));
return;
}
}
}
ArrayList<Explode> explodesToRemove = new ArrayList<>();
for (Explode explode: explodes){
explode.update(delta);
if (explode.remove)
explodesToRemove.add(explode);
}
explodes.removeAll(explodesToRemove);
for (Bullet bullet: bullets){
for (Target target: targets){
if (bullet.getCollisionRect().collidesWith(target.getCollisionRect())){
targetsToRemove.add(target);
bulletsToRemove.add(bullet);
score+=5;
explodes.add(new Explode(target.getX(), target.getY()));
sound.play(1f, 1.3f, 0f);
}
}
}
targets.removeAll(targetsToRemove);
bullets.removeAll(bulletsToRemove);
//Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.batch.begin();
spritebg.draw(game.batch);
game.batch.draw(blueBarO, 0, 575, blueBarO.getWidth(), blueBarO.getHeight());
game.batch.draw(redBarO, 0, 550, redBarO.getWidth(), redBarO.getHeight());
game.batch.draw(greenBarO, 0, 525, greenBarO.getWidth(), greenBarO.getHeight());
game.batch.draw(pinkBarO, 0, 600, pinkBarO.getWidth(), pinkBarO.getHeight());
game.font.draw(game.batch, "SCORE: " + score, 40, Gdx.graphics.getHeight() - 40 );
for (Bullet bullet: bullets){
bullet.render(game.batch);
}
for (Target target: targets){
target.render(game.batch);
}
for (Explode explode: explodes){
explode.render(game.batch);
}
if (health == 0) greenBar.setSize(greenBar.getWidth(), 0f);
game.batch.draw(greenBar, 0, 525, greenBar.getWidth() * health, greenBar.getHeight());
game.batch.draw(redBar, 0, 550, redBar.getWidth(), redBar.getHeight());
game.batch.draw(blueBar, 0, 575, blueBar.getWidth(), blueBar.getHeight());
game.batch.draw(pinkBar, 0, 600, pinkBar.getWidth(), pinkBar.getHeight());
game.batch.draw(playerImage, player.x, player.y, player.width, player.height);
game.batch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
if (a) player.x -= 450 * Gdx.graphics.getDeltaTime();
if (b) player.x += 450 * Gdx.graphics.getDeltaTime();
if (player.x < 65f + imgbtnLeft.getWidth() + imgbtnRight.getWidth())
player.x = 65f + imgbtnLeft.getWidth() + imgbtnRight.getWidth();
if (player.x > Gdx.graphics.getWidth() - 350f)
player.x = Gdx.graphics.getWidth() - 350f;
}
@Override
public void dispose () {
musicbg.dispose();
laser.dispose();
stage.dispose();
skin.dispose();
sound.dispose();
}
}
我在字里行间阅读,但看起来您必须在Bullet/Target/Explosion的构造函数中加载纹理,因为我没有看到您将纹理或TextureRegion引用传递给它们的构造函数或
render
方法
你应该在一个类中加载所有纹理,并传递对游戏对象的引用,以便它们“借用”和绘制。否则,您会无缘无故地加载同一图像的多个副本
此外,纹理是一次性的,这意味着它使用本机内存,并且在让垃圾收集器接收它之前必须对其调用dispose()
。否则,本机内存将泄漏
在您的情况下,所有这些子弹、目标和爆炸都会一遍又一遍地加载许多纹理,并且在删除它们时从不处理它们
关于你关于SpriteBatch的问题。是的,您应该在实例化它的同一个类中处理它,并且dispose()
是正确的处理位置
编辑,裸体示例:
public class Assets implements Disposable {
public final Texture horse;
public final Texture bullet;
// etc.
public Assets (){
horse = new Texture("horse.png");
//...
}
public void dispose(){
horse.dispose();
//...
}
}
public class Zero implements Screen, InputProcessor {
private final Assets assets;
//...
public Zero (){
assets = new Assets();
//...
}
//...
public void dispose(){
assets.dispose();
//...
}
}
public class Bullet {
//...
public void render(SpriteBatch batch, Assets assets){
batch.render(assets.bullet, /*...*/);
}
}
子弹、目标、爆炸类的数据成员是什么。检查是否值得在render方法中创建这些类的对象。如果频繁创建对象,请尝试使用池API。在渲染方法内创建容器(Arraylist)??注释掉新语句,并检查内存泄漏是否仍然发生。逐一进行联合国评论,找出问题所在。当然,正如Aryan所说,不要在render方法(每帧)中分配它们,而是在create方法中分配它们。你是对的,我在它们的构造函数中加载纹理。如果你能给我一个例子,让我用一个类来处理我的纹理,然后通过引用传递它们,我将不胜感激。谢谢。@ZerOjMac我添加了一个示例。但您还应该研究LibGDX的AssetManager类,因为它是处理资产的更好方法,而不是自己手动加载每个资产。在您了解如何使用它之后,我建议您查找CoveTools库,并使用其AssignmentAssetManager删除大量样板代码。非常感谢您提供的信息,我将查看您提到的内容。@ZerOjMac不客气。另外,我注意到另一件不相关的事情。。。在渲染循环中创建许多新的ArrayList。这可能会导致帧速率出现小的停顿,因为它必须分配ArrayList的备份数组,可能必须在填充时调整其大小(这意味着分配一个更大的数组并复制第一个数组),然后必须取消分配备份数组。我建议对这些列表使用最终成员字段,以便只分配一次。这可能有点晚了,但多亏了你,我成功开发了我的第一个游戏。它仍然没有完成,因为我仍然有想法,但看看它。
public class Assets implements Disposable {
public final Texture horse;
public final Texture bullet;
// etc.
public Assets (){
horse = new Texture("horse.png");
//...
}
public void dispose(){
horse.dispose();
//...
}
}
public class Zero implements Screen, InputProcessor {
private final Assets assets;
//...
public Zero (){
assets = new Assets();
//...
}
//...
public void dispose(){
assets.dispose();
//...
}
}
public class Bullet {
//...
public void render(SpriteBatch batch, Assets assets){
batch.render(assets.bullet, /*...*/);
}
}