6

ゲームを実行していますが、ランダムに途切れています。これにより、GCが実行されていると思います。コードを検索した後、1秒あたり4〜5のようなGC_CONCURRENTメッセージがたくさん表示されます。

12-04 22:14:22.018: D/dalvikvm(4757): GC_CONCURRENT freed 510K, 7% free 10139K/10823K, paused 4ms+6ms
12-04 22:14:22.288: D/dalvikvm(4757): GC_CONCURRENT freed 497K, 7% free 10139K/10823K, paused 3ms+7ms
12-04 22:14:22.558: D/dalvikvm(4757): GC_CONCURRENT freed 497K, 7% free 10139K/10823K, paused 3ms+6ms
12-04 22:14:22.823: D/dalvikvm(4757): GC_CONCURRENT freed 497K, 7% free 10139K/10823K, paused 3ms+7ms

犯人をレンダリングクラスに絞り込みました。私はLibGdx(これは私の最初のLibGdxアプリです)を学んでいて、誰かが問題を見ることができるかどうか疑問に思っていました。

public void render(){

    batch.begin();

    //Draw background
    batch.draw(skin.getSprite("background_chapter"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT);

    //draw tiles
    bIter = world.getBlocks().iterator();
    while(bIter.hasNext()){
        tile = bIter.next();

        switch(tile.getType()){
        case Values.ICE:
            continue;
        (many more cases...)
        }   
        batch.draw(skin.getSprite(tr), tile.getPosition().x*scaleX, tile.getPosition().y*scaleY, tile.getBounds().width*scaleX, tile.getBounds().height*scaleY);
    }

    //put ice on top of other level elements, non mobile ice on bottom
    bIter = world.getBlocks().iterator();
    while(bIter.hasNext()){
        tile = bIter.next();
        if(tile.getType() == Values.ICE && tile.getCollide() == false){
         batch.draw(skin.getSprite("ice"), tile.getPosition().x*scaleX, tile.getPosition().y*scaleY, tile.getBounds().width*scaleX, tile.getBounds().height*scaleY);
        }
    }

            //mobile ice on top
    bIter = world.getBlocks().iterator();
    while(bIter.hasNext()){
        tile = bIter.next();
        if(tile.getType() == Values.ICE && tile.getCollide() == true){
             batch.draw(skin.getSprite("ice"), tile.getPosition().x*scaleX, tile.getPosition().y*scaleY, tile.getBounds().width*scaleX, tile.getBounds().height*scaleY);
        }
    }

    //pauly on top
    batch.draw(skin.getSprite("pauly_moving"), pauly.getBounds().x*scaleX, pauly.getBounds().y*scaleY, pauly.getBounds().width*scaleX, pauly.getBounds().height*scaleY);

    batch.draw(skin.getSprite("background_chapter"), 0+(SIDE_EDGE*scaleX), (9.6f*scaleY), CAMERA_WIDTH, 1*scaleY);


    //draw UI elements
    batch.draw(skin.getSprite("pause_menu_icon"), CAMERA_WIDTH-(SIDE_EDGE*scaleX), CAMERA_HEIGHT-(0.25f*scaleY), 1*scaleX, 1*scaleY);
    batch.draw(skin.getSprite("restart_menu_icon"), SIDE_EDGE*scaleX, CAMERA_HEIGHT-(0.25f*scaleY), 1*scaleX, 1*scaleY);

    font.draw(batch, "Moves: "+pauly.getCurrentMoves()+"/ "+world.getLevel().getMovesNeeded(), 2f*scaleX,10.1f*scaleY);

    font.draw(batch, world.getLevel().getTitle(), 6f*scaleX,10.1f*scaleY);
    //draws the FPS on screen
    font.draw(batch, "FPS: "+(Gdx.graphics.getFramesPerSecond()), 12f*scaleX,10.1f*scaleY);

    if(world.getState()==Values.PAUSED){
        batch.draw(skin.getSprite("pause_menu"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT);
        //Gdx.app.log("WorldRenderer", "Game Paused");
    } else if(world.getState()==Values.LOOSE){
        batch.draw(skin.getSprite("die_menu"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT);
        //Gdx.app.log("WorldRenderer", "Game Paused");
    } else if(world.getState()==Values.WIN){
        batch.draw(skin.getSprite("win_menu"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT);
        //Gdx.app.log("WorldRenderer", "Game Paused");
    } 

    batch.end();

}

ブロックをコメントアウトしようとしましたが、途中でさらにGC呼び出しが発生しているようですが、どこでもGC呼び出しが発生しているようです。

編集:答え

以下の回答を使用して、DDMSを使用して割り当てを確認しました。1秒間に約100個の新しいオブジェクトを作成していました...float[]、テクスチャ領域、スプライト...すべてに関連付けられています

skin.getSprite("texture");

各呼び出しは、float []、テクスチャ領域、およびスプライトを作成していました。DDMSの割り当てを調べてくれてありがとう。解決策は、コンストラクター関数でスプライト(フィールド)を作成し、それらを順番に呼び出すことでYulが言ったことです。

したがって、この...

batch.draw(skin.getSprite("background_chapter"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT);

これに変更しました...

//in constructor()
background = skin.getSprite("background_chapter");

//in render()
batch.draw(background, 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT);

これでGC呼び出しはなくなり、ゲームはよりスムーズに実行されているようです。

ありがとう

4

1 に答える 1

3

DDMS Allocation Trackerツールを使用して、特定の問題がどこにあるかを追跡します。(Androidデバイスでアプリを実行し、DDMSウィンドウを開き、[割り当てトラッカー]タブに切り替え、[デバイス]タブでプロセスを選択し、ゲームを開始し、[追跡を開始]をクリックし、数秒待ってから[割り当てを取得]をクリックします"、データの表を見てください。threadIdでの並べ替えは、レンダリングスレッドのアクティビティを他のバックグラウンドスレッドから分離するための優れた方法であることがわかりました。)

イテレータは一時オブジェクトを作成するため、特にレンダリングループでは、明示的なインデックスを使用する必要があります。

文字列の連結により、一時オブジェクトも作成されます。

おそらく他にもたくさんの微妙な場所にメモリが割り当てられていますが、これを理解する正しい方法は、適切なツールを使用することです。

于 2012-12-05T14:44:03.643 に答える