1

cocos2d のバックグラウンド スレッドでテクスチャをレンダリングしようとしましたが、うまくいきましたが、使用されなくなったテクスチャを何らかの理由で解放できません。

最初に 2 つの画像を非同期で読み込み、次に新しい画像をレンダリングするバックグラウンド タスクを実行します。私が言うように、問題なく動作していますが、問題は、これらの関数を数回呼び出した後にアプリがクラッシュすることです。これ以上クリーンアップする方法がわかりません。使用可能なメモリをログアウトすると、毎回 10 ~ 15 mb を失っていることがわかります (gfx1 と gfx2 は Retina フルスクリーン背景です)。

問題はこれらのコード行内にあるに違いありません。それらを削除すると、メモリの問題はなくなり、アプリのプロファイリングによるとリークはありません!

テクスチャはNSMutableArray. インデックス 0 にテクスチャがあり、新しいテクスチャをレンダリングして位置 1 に追加します。スプライトを置き換えた後、インデックス 0 の (現在は古い) テクスチャを削除しようとすると、新しいテクスチャがインデックス 0 になるので、実行できます。この機能を繰り返します。

だからここにコードがあります

- (void) startBuildingTextureInBackground {
    [[CCTextureCache sharedTextureCache] addImageAsync:@"gfx1.png"
                                                target:self
                                              selector:@selector(imageLoaded:)];
}

- (void) imageLoaded: (id) obj {
    rtxTexture1 = [[CCTextureCache sharedTextureCache] textureForKey:@"gfx1.png"];
    [[CCTextureCache sharedTextureCache] addImageAsync:@"gfx2.png"
                                                target:self
                                              selector:@selector(imageLoaded2:)];
}

- (void) imageLoaded2: (id) obj {
    rtxTexture2 = [[CCTextureCache sharedTextureCache] textureForKey:@"gfx2.png"];
    [self performSelectorInBackground:@selector(buildRtxTexture) withObject:nil];
}

- (void) buildRtxTexture {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    EAGLSharegroup *sharegroup = [[[[CCDirector sharedDirector] openGLView] context] sharegroup];
    EAGLContext *k_context = [[[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:sharegroup] autorelease];
    [EAGLContext setCurrentContext:k_context];
    [[CCDirector sharedDirector] setGLDefaultValues];

    CCSprite* gfx1 = [CCSprite spriteWithTexture:rtxTexture1];
    [rendernode addChild:gfx1];

    CCSprite* gfx2 = [CCSprite spriteWithTexture:rtxTexture2];
    [rendernode addChild:gfx2];

    CCRenderTexture* rtx = [CCRenderTexture renderTextureWithWidth:512
                                                            height:320
                                                       pixelFormat:kTexture2DPixelFormat_RGBA4444];

    [rtx beginWithClear:0 g:0 b:0 a:0];
    [rendernode visit];

    [rtx end];

    [rendernode removeChild:gfx1 cleanup:YES];
    [rendernode removeChild:gfx2 cleanup:YES]; 

    [[CCTextureCache sharedTextureCache] removeTexture:rtxTexture1];
    [[CCTextureCache sharedTextureCache] removeTexture:rtxTexture2];

    [EAGLContext setCurrentContext:nil];
    [self performSelectorOnMainThread:@selector(textureLoaded:) withObject:rtx.sprite.texture waitUntilDone:YES]; 

    [pool release];
}

- (void) textureLoaded:(CCTexture2D*) newTexture {
    [textures addObject:newTexture];
}

- (void) replaceTexture {
    if (rtxSprite != nil) {
        [spriteDisplay removeChild:rtxSprite cleanup:YES];
        [[CCTextureCache sharedTextureCache] removeTexture:[textures objectAtIndex:0]];
        [textures removeObjectAtIndex:0];
    }

    rtxSprite = [CCSprite spriteWithTexture:[textures objectAtIndex:0]];
    rtxSprite.scaleY = -1;
    [spriteDisplay addChild: rtxSprite];
}
4

2 に答える 2

0

コンテキストをnilに設定する前に呼び出す[pool release]と、問題が解決します。

于 2012-05-07T14:17:54.080 に答える
0
  1. コードのデバッグを試みます。ブレーク ポイントまたは NSLog/CCLOG を追加して、CCTexture2D/CCRenderTexture の init/dealloc メソッドの呼び出しを追跡します。

  2. バックグラウンド スレッドで CCRenderTexture に問題が発生する可能性があります。CCRenderTexture を使用してテクスチャを操作しようとすると、予期しない結果になりました (黒いテクスチャまたはクラッシュ)。これは、メイン ループで OpenGL 関数も呼び出し、OpenGL がステート マシンであるためです。回避策は、メイン スレッドで CCRenderTexture を使用してメソッドを呼び出すことでした (performSelectorOnMainThread)。

于 2012-05-07T11:23:52.393 に答える