安卓工作室Libgdx内存问题

3

我的应用程序有些问题。有时会出现卡顿的情况,并显示“GC_CONCURRENT freed”的信息。我使用MAT工具查看了消耗大量内存的原因,发现一个对象列表占用了很多内存。问题在于我的游戏中有方块,我需要确定玩家是否踩在它们上面,所以我使用了这个列表。目前我有200个方块,但我将拥有更多,我不认为它们应该使用这么多内存,我该怎么办来解决这个问题?这是方块类的代码:

package com.NeverMind.DontFall.android;

import android.util.Log;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

/**
 * Created by user on 20-Aug-15.
 */
public class blockClass {
    private SpriteBatch spriteBatch;
    public float x, y, sizeX = 100, sizeY = 100, startTime;
    private boolean isTouched = false;
    private Texture texture;
    Sprite blockSprite;
    public blockClass(float sentX, float sentY, Texture sentTexture, float scaleX, float scaleY){
        x = sentX;
        y = sentY;
        sizeY *= scaleY;
        sizeX *= scaleX;
        spriteBatch = new SpriteBatch();
        texture = sentTexture;
        blockSprite = new Sprite(texture);
        startTime = System.currentTimeMillis();
    }
    public void draw(float cameraX, float cameraY) {
        spriteBatch.begin();
        spriteBatch.draw(blockSprite, x + cameraX, y + cameraY, sizeX, sizeY);
        spriteBatch.end();
    }
    public void update(float posX, float posY, boolean immune){
        if (isTouched == false && immune == false)
            if (touched(posX, posY) )
                isTouched = true;
        if (isTouched == true) {
            y -= 10;
        }
    }
    public boolean touched (float posX, float posY)
    {
        if (posX >= x && posX < x + sizeX && posY == y + sizeY)
            return true;
        return false;
    }
    public boolean toKill (float posY){
        if (isTouched && y < posY - 1000)
            return true;
        return false;
    }
}

1
你是在游戏开始前还是在运行时创建你的200个区块? - Saeed Masoumi
这是一个全局变量,因此列表在游戏启动时创建,但仅创建一次。创建列表后,我将对象放入其中的方法是create(),该方法仅运行一次。 - Never Mind
1
你在游戏渲染时销毁对象吗? - Saeed Masoumi
是的,当我不再需要那个对象时。 - Never Mind
2
所以你的每个块都实例化了一个SpriteBatch?!!你在整个游戏中应该只有一个SpriteBatch,并将其重复使用于所有对象。SpriteBatch使用大量本地内存,拥有多个SpriteBatch完全是多余的。顺便说一下,在您将其从范围中丢失到GC之前,必须对其调用“dispose”。 - Tenfour04
显示剩余3条评论
1个回答

5

GC_CONCURRENT freed的意思是垃圾回收器被调用,因为要销毁对象(例如将null赋值给它们)。

有一个概念叫做对象池,它重复使用死亡对象而不是销毁它,并从池中获取对象而不是创建新对象,这样就不会有GC调用,同样也没有GC_CONCURRENT freed


你确定吗?你可能误解了,我认为它不应该暂停我的游戏,这会导致延迟,例如:GC_CONCURRENT释放了355K,15%空闲11033K / 12935K,暂停17ms + 2ms,总计58ms。 - Never Mind
2
是的,我确定池化是避免垃圾回收调用的常见方法。根据您的评论“是的,当我不再需要该对象时。”,您通过销毁对象来调用垃圾回收。 - Saeed Masoumi
gdx提供了自己的池类,如果你不想使用它,可以编写自己的逻辑。作为一个经验法则,我的对象数量是一次活动的最大对象数量加上3个,以避免任何空指针,并通过操作它们来分配和保存内存和垃圾回收调用。一个例子可以是射击游戏中的子弹,如果我每次都创建一个新对象然后将其置为空,那么垃圾回收会导致游戏卡顿,所以最好在显示屏范围结束后重用子弹。 - Kumar Saurabh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接