編集: 前のシーンの dealloc メソッドと cleanup メソッドの両方に次のコードを追加しました (replaceScene を呼び出す元のシーンですが、効果はありません。InstructionScene がメモリを作成してから 1/2/5 秒後でも、にはまだ前のシーンのアセットが含まれています.それらを強制的に削除する唯一の方法は, シーンが作成されてから 0.1f 秒後に新しいシーンからそれらを削除することです (コールバックを介して). これはちょっと変です.
前のシーンのクリーンアップと daelloc メソッドのコードは次のとおりです。
-(void) cleanup
{
CCLOG(@"");
CCLOG(@"");
CCLOG(@"PlanetSelection Menu cleanup");
CCLOG(@"");
[super cleanup];
[planetLayer removeAllChildrenWithCleanup:YES];
[self removeAllChildrenWithCleanup: YES];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFramesFromFile:textureFileName];
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
[CCAnimationCache purgeSharedAnimationCache];
}
-(void) dealloc
{
CCLOG(@"Dealloc gets caled");
[CCAnimationCache purgeSharedAnimationCache];
[[CCDirector sharedDirector] purgeCachedData];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFramesFromFile:textureFileName];
}
元の質問:
ゲームにいくつかのシーンがあり、これまでのところ、各シーンの最初に次のコードを使用して、以前に保存したテクスチャを削除しました。ただし、これが機能しない場合があります。シーン (A と呼びましょう) を、スプライトがなく、フォント イメージ シートから作成されたラベルのみの新しいシーン (B と呼びましょう) に置き換える場合です。
[[CCDirector sharedDirector] replaceScene: [InstructionsScene sceneWithLevelName:FIRST_LEVEL]];
次の呼び出しは効果がないように見えるため、新しいオブジェクトの作成が速すぎます。
-(id) initWithLevelName:(LevelName)name
{
if ((self = [super init]))
{
//Remove stuff from previous scene
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames]; //Not really necessary
//Use these
[[CCTextureCache sharedTextureCache] removeUnusedTextures]; //Not really needed
[[CCTextureCache sharedTextureCache] removeAllTextures];
[[CCDirector sharedDirector] purgeCachedData];
[CCAnimationCache purgeSharedAnimationCache];
....
}
}
シーン置換メソッドが呼び出されている瞬間に、2 つの CCLayer (CCScane) オブジェクトが同時にアクティブになります。ただし、前のシーンのテクスチャは削除されません。スプライト シートが追加され、Instruction シーンで使用されている場合、同じコードが完全に機能します。これを微調整するには、セレクターへのコールバックを使用して 0.1fの後のすべてのテクスチャを削除しますが、これはあまりエレガントでスムーズではありません。
[self runAction:[CCSequence actionOne:[CCDelayTime actionWithDuration:0.1f] two:[CCCallFunc actionWithTarget:self selector:@selector(removeStuffFromPreviousScene)]]];
これは既知の問題ですか? 潜在的なクラッシュを引き起こす可能性があります。
試していただけるように、ここにコードを貼り付けます。
//
// InstructionsScene.h
//
// Created by mm24 on 09/09/13.
// Copyright 2013 mm24. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#import "CommonEnumerations.h"
@interface InstructionsScene : CCLayer {
LevelName levelName;
float startTime;
CCLabelBMFont * levelNameTitle;
CCLabelBMFont * levelSubtitle;
CCLabelBMFont * instructionsHeader;
CCLabelBMFont * instructions;
}
+(id)sceneWithLevelName:(LevelName)name;
@end
//
// InstructionsScene.m
//
// Created by mm24 on 09/09/13.
// Copyright 2013 mm24. All rights reserved.
//
#import "InstructionsScene.h"
#import "ShooterScene.h"
#import "AppDelegate.h"
#import "mach/mach.h"
@implementation InstructionsScene
+(id)sceneWithLevelName:(LevelName)name
{
CCScene * scene = [CCScene node];
InstructionsScene * layer = [[self alloc] initWithLevelName:name];
[scene addChild:layer];
return scene;
}
-(id) initWithLevelName:(LevelName)name
{
if ((self = [super init]))
{
//Remove stuff from previous scene
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
//Use these
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
[[CCTextureCache sharedTextureCache] removeAllTextures];
[[CCDirector sharedDirector] purgeCachedData];
[CCAnimationCache purgeSharedAnimationCache];
//Try out and use it. Not compulsory
[self removeAllChildrenWithCleanup: YES];
CCLOG(@"init with level name");
levelName = name;
startTime = 10.0f;
levelNameTitle = [CCLabelBMFont labelWithString:@"Title" fntFile:@"bitmapFontTest.fnt"];
levelNameTitle.position = CGPointMake(160.0f, 420.0f);
levelNameTitle.anchorPoint = CGPointMake(0.5f, 0.5f);
levelNameTitle.scale = 1.3f;
[self addChild:levelNameTitle z:1] ;
levelSubtitle = [CCLabelBMFont labelWithString:@"Subtitle" fntFile:@"bitmapFontTest.fnt"];
levelSubtitle.position = CGPointMake(160.0f, 400.0f);
levelSubtitle.anchorPoint = CGPointMake(0.5f, 0.5f);
levelSubtitle.scale = 0.7f;
[self addChild:levelSubtitle z:1] ;
instructionsHeader = [CCLabelBMFont labelWithString:@" Instructions " fntFile:@"bitmapFontTest.fnt"];
instructionsHeader.position = CGPointMake(160.0f, 240.0f);
instructionsHeader.anchorPoint = CGPointMake(0.5f, 0.5f);
instructionsHeader.scale = 0.7f;
[self addChild:instructionsHeader z:1] ;
instructions = [CCLabelBMFont labelWithString:@"Press any key" fntFile:@"bitmapFontTest.fnt"];
instructions.position = CGPointMake(160.0f, 200.0f);
instructions.anchorPoint = CGPointMake(0.5f, 0.5f);
instructions.scale = 0.7f;
[self addChild:instructions z:1] ;
[[CCDirector sharedDirector] resume];
// [self runAction:[CCSequence actionOne:[CCDelayTime actionWithDuration:0.1f] two:[CCCallFunc actionWithTarget:self selector:@selector(removeStuffFromPreviousScene)]]];
[self runAction:[CCSequence actionOne:[CCDelayTime actionWithDuration:1.0f] two:[CCCallFunc actionWithTarget:self selector:@selector(report_memory)]]];
[self runAction:[CCSequence actionOne:[CCDelayTime actionWithDuration:2.0f] two:[CCCallFunc actionWithTarget:self selector:@selector(report_memory)]]];
[self runAction:[CCSequence actionOne:[CCDelayTime actionWithDuration:5.0f] two:[CCCallFunc actionWithTarget:self selector:@selector(report_memory)]]];
[self callBackReplace];
}
return self;
}
-(void) removeStuffFromPreviousScene
{
//Use these
[[CCSpriteFrameCache sharedSpriteFrameCache] removeSpriteFrames];
[[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
//Use these
[[CCTextureCache sharedTextureCache] removeUnusedTextures];
[[CCTextureCache sharedTextureCache] removeAllTextures];
[[CCDirector sharedDirector] purgeCachedData];
[CCAnimationCache purgeSharedAnimationCache];
}
-(void) report_memory {
CCLOG(@"");
CCLOG(@"");
CCLOG(@"InstructionScene info:");
CCLOG(@"");
[[CCTextureCache sharedTextureCache] dumpCachedTextureInfo];
struct task_basic_info info;
mach_msg_type_number_t size = sizeof(info);
kern_return_t kerr = task_info(mach_task_self(),
TASK_BASIC_INFO,
(task_info_t)&info,
&size);
if( kerr == KERN_SUCCESS ) {
NSLog(@"Memory in use (in bytes): %u", info.resident_size);
} else {
NSLog(@"Error with task_info(): %s", mach_error_string(kerr));
}
}
-(void) nextSuggestionPressed
{
[self stopAllActions];
[self callBackReplace];
}
-(void) callBackReplace
{
[self runAction:[CCSequence actions:
[CCDelayTime actionWithDuration:startTime] ,
[CCCallFunc actionWithTarget:self selector:@selector(replaceWithShooterScene)],
nil]
];
}
-(void) replaceWithShooterScene
{
[[CCDirector sharedDirector] replaceScene:[ShooterScene sceneWithLevelName:levelName]];
}
@end