LibGDX输入模块之内存管理

游戏是资源密集型的应用。 图像和声音效果可能占用大量的RAM。 此外,这些资源大部分不由Java垃圾回收器管理。 相反,它们由本地驱动程序管理。 让垃圾收集器决定什么时候从RAM释放5M的纹理也不是一个太明智的想法。

我们希望对我们资源的生命周期进行细粒度的控制。 libgdx中有多个类需要人为在生命周期结束时进行手动处理。 它们都实现了一个通用的Disposable 接口,它指出了这个类的实例需要在生命周期结束时手动处理。 未能处置资源将导致严重的内存泄漏!

以下类别需要手动处理(可能不完整):
AssetManager
Bitmap
BitmapFont
BitmapFontCache
CameraGroupStrategy
DecalBatch
ETC1Data
FrameBuffer
Mesh
Model
ModelBatch
ParticleEffect
Pixmap
PixmapPacker
Shader
ShaderProgram
Shape
Skin
SpriteBatch
SpriteCache
Stage
Texture
TextureAtlas
TileAtlas
TileMapRenderer
com.badlogic.gdx.physics.box2d.World
all bullet classes

一旦不再需要资源,就应该处理资源,释放与之相关的内存。 访问已被清理的资源将导致未定义的错误,因此请确保清除所有已处理资源的引用。
当有疑问是否需要处理特定的类时,请检查它是否具有从com.badlogic.gdx.utils的Disposable接口实现的dispose()方法。 如果是,您现在正在使用本地资源。

您可要clone LibGDX的源码来寻找更多本地资源的类.

对象池

与其每次都创建一个对象,我们可以创建一个对象池来重用非活动的对象,当你需要一个新的对象时,你可以从对象池中获取,如果对象池中存在未被使用的对象,那么对象池会将其返回,如果对象池不存在空闲的对象,那么对象池会创建一个新的对象并返回它,这样对象被反复利用有利于内存的管理.

这对于对象产生频繁的游戏(如子弹,障碍物,怪物等)的内存管理至关重要。

Libgdx提供了几个工具,便于创建对象池:

  1. Poolable 接口
  2. Pool
  3. Pools

实现Poolable接口意味着您将在对象中具有一个reset()方法,当您释放对象时,该方法将被自动调用。
以下是汇集子弹对象的一个简单示例:

public class Bullet implements Poolable {

    public Vector2 position;
    public boolean alive;

    /**
     * Bullet constructor. Just initialize variables.
     */
    public Bullet() {
        this.position = new Vector2();
        this.alive = false;
    }
    
    /**
     * Initialize the bullet. Call this method after getting a bullet from the pool.
     */
    public void init(float posX, float posY) {
        position.set(posX,  posY);
        alive = true;
    }

    /**
     * Callback method when the object is freed. It is automatically called by Pool.free()
     * Must reset every meaningful field of this bullet.
     */
    @Override
    public void reset() {
        position.set(0,0);
        alive = false;
    }

    /**
     * Method called each frame, which updates the bullet.
     */
    public void update (float delta) {
        
        // update bullet position
        position.add(1*delta*60, 1*delta*60);
        
        // if bullet is out of screen, set it to dead
        if (isOutOfScreen()) alive = false;
    }
}

在你的游戏逻辑中(控制类):

public class World {

    // array containing the active bullets.
    private final Array<Bullet> activeBullets = new Array<Bullet>();

    // bullet pool.
    private final Pool<Bullet> bulletPool = new Pool<Bullet>() {
    @Override
    protected Bullet newObject() {
        return new Bullet();
    }
    };

    public void update(float delta) {
    
        // if you want to spawn a new bullet:
        Bullet item = bulletPool.obtain();
        item.init(2, 2);
        activeBullets.add(item);

        // if you want to free dead bullets, returning them to the pool:
        Bullet item;
        int len = activeBullets.size;
        for (int i = len; --i >= 0;) {
            item = activeBullets.get(i);
            if (item.alive == false) {
                activeBullets.removeIndex(i);
                bulletPool.free(item);
            }
        }
    }
}

Pools类提供静态方法来动态创建任何对象的池(使用Reflection Pool反射对象池)。 在上面的例子中,可以这样使用。

private final Pool<Bullet> bulletPool = Pools.get(Bullet.class);

如何使用对象池

Pool<>管理单一类型的对象。 对象通过调用obtain()方法从特定Pool获取实例,然后通过调用free()将其释放到Pool中。 池中的对象可以可选地实现Pool.Poolable接口(只需要存在一个reset()方法),在这种情况下,当池返回到池时,池将自动重置对象。对象按需分配(所以如果您从不调用获取,则池将不包含任何对象)。

您必须实现自己的Pool <>子类,因为newObject方法是抽象的。

对象池注意事项

提防对象池的对象引用泄露,如果对象在外部仍在使用,但是你调用了对象池的free()方法,会导致外部引用无效,如果对象在放入对象池中没有完全被重置,那么当再次获取的时候,获取到的对象可能会有细微的错误.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容