0

我使用 ARC 进行内存管理。

在游戏开始之前,我使用了一个预加载场景,在该场景中我加载了很多将在我的游戏中使用的 CCParticleSystemQuad 对象。这部分一切顺利,这是我的代码:

//
//  ReadySteadyGo.m

//
//  Created by Nik on 23/05/13.
//  Copyright 2013 __MyCompanyName__. All rights reserved.
//

#import "ReadySteadyGoLayer.h"
#import "QuickStartLayer.h"


@implementation ReadySteadyGoLayer
// Helper class method that creates a Scene with the ReadySteadyLayer as the only child.
+(CCScene *) scene{
    // 'scene' is an autorelease object.
    CCScene *scene = [CCScene node];

    // 'layer' is an autorelease object.
    ReadySteadyGoLayer *layer = [ReadySteadyGoLayer node];

    // add layer as a child to scene
    [scene addChild: layer];

    // return the scene
    return scene;
}
@synthesize particleExplosion;


// on "init" you need to initialize your instance
-(id) init
{
    // always call "super" init
    if( (self=[super init]) ) {

        compteur = 3;
        plus10LablesArray = [[NSMutableArray alloc] initWithCapacity:400];
        whiteParticlesArray = [[NSMutableArray alloc] initWithCapacity:500];
        bombParticlesArray = [[NSMutableArray alloc] initWithCapacity:50];
        self.particleExplosion = [[CCParticleSystemQuad alloc] init];
        bombExplosion = [[CCParticleSystemQuad alloc] init];
        plus10Label = [[CCLabelTTF alloc] init];
        displayCompteur = [[CCLabelTTF alloc] init];
        self.particleExplosion = [CCParticleSystemQuad particleWithFile:@"whiteExplosion.plist"];
        bombExplosion = [CCParticleSystemQuad particleWithFile:@"explosion.plist"];
    }

    [self schedule:@selector(initAll)];
    [self schedule:@selector(compt)];
    return self;
}

-(void)initAll{
    // Create a new NSOperationQueue instance.
    operationQueue = [[NSOperationQueue alloc] init];
    // Create a new NSOperation object using the NSInvocationOperation subclass.
    // Tell it to run the counterTask method.
    NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self
                                                                            selector:@selector(initWhiteParticles)
                                                                              object:nil];
    NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self
                                                                             selector:@selector(initBombParticles)
                                                                               object:nil];
    NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self
                                                                             selector:@selector(initPlus10Labels)
                                                                               object:nil];
    // Add the operation to the queue and let it to be executed.
    [operationQueue addOperation:operation1];
    [operationQueue addOperation:operation2];
    [operationQueue addOperation:operation3];
    [self unschedule:@selector(initAll)];

}

- (void)compt{
   CGSize winSize = [CCDirector sharedDirector].winSize;

    if (compteur == 3){
        displayCompteur = [CCLabelTTF labelWithString:[NSString stringWithFormat:@"%i...", compteur] fontName:@"Helvetica" fontSize:120];
        displayCompteur.position = ccp(winSize.width/2, winSize.height/2);
        [self addChild:displayCompteur z:1000];
        compteur--;
        [self unschedule:@selector(compt)];
        [self schedule:@selector(boucle) interval:1.0f];
    }
    else if (compteur == 2){
        displayCompteur.string = [NSString stringWithFormat:@"%i..", compteur];
        compteur--;
        [self schedule:@selector(compt) interval:1.0f];
    }
    else if (compteur == 1){
        displayCompteur.string = [NSString stringWithFormat:@"%i.", compteur];
        compteur--;
        [self schedule:@selector(compt) interval:1.0f];
    }
    else if (compteur == 0){
        displayCompteur.string  = @"GO";
        displayCompteur.fontSize = 25;
        compteur--;
        [self schedule:@selector(compt) interval:1.0f];
    }
    else{
        [self unschedule:@selector(compt)];
        [[CCDirector sharedDirector] pushScene:[QuickStartLayer scene:plus10LablesArray:whiteParticlesArray: bombParticlesArray]];
    }

}

- (void)initWhiteParticles{ 
    int index = 0;
    for (index = 0; index < 500; index++) {
        self.particleExplosion = [CCParticleSystemQuad particleWithFile:@"whiteExplosion.plist"];
        [whiteParticlesArray  performSelectorOnMainThread:@selector(addObject:) withObject:self.particleExplosion waitUntilDone:NO];
    }
}

- (void)initBombParticles{
    int index = 0;
    for (index = 0; index < 50; index++) {
        bombExplosion = [CCParticleSystemQuad particleWithFile:@"explosion.plist"];
        [bombParticlesArray  performSelectorOnMainThread:@selector(addObject:) withObject:bombExplosion waitUntilDone:NO];
    }
}

- (void)initPlus10Labels{
    int index = 0;
    for (index = 0; index < 400; index++) {
        plus10Label = [CCLabelTTF labelWithString:@"+10" fontName:@"Helvetica" fontSize:20];
        [plus10LablesArray performSelectorOnMainThread:@selector(addObject:) withObject:plus10Label waitUntilDone:NO];
    }
}

@end

问题是当我签入 Instruments (allocations) 时,我可以看到 [CCParticleSystemQuad alloc memory] ​​每次都在增加。使用我的游戏 15 分钟后,它崩溃了...

当我使用我的粒子时,我会这样做:

explosion = [_whiteParticlesArray objectAtIndex:nextWhiteParticle];
nextWhiteParticle++;
explosion.position = ccp(posX, posY);
[particleToDelete addObject:explosion];
[self addChild: explosion];

我创建了一个清理粒子的函数:

- (void)cleanParticles{
    for (int i = 0; i < [particleToDelete count]; i++) {
        id object = [particleToDelete objectAtIndex:i];
        [particleToDelete removeObject:object];
        [self removeChild:object cleanup:YES];
    }
}

在游戏结束时,我要做的是:

[self unschedule:@selector(countDown:)];
[self unschedule:@selector(addAllSprites:)]
[self unschedule:@selector(displayScore:)];
[self unschedule:@selector(cleanParticles)];
[self unschedule:@selector(cleanLabels)];
[_whiteParticlesArray removeAllObjects];
[_bombParticlesArray removeAllObjects];
[_plus10LabelsArray removeAllObjects];
[self removeChild:_spriteSheet cleanup:YES];

所以我删除了所有对象,ARC应该清理这些对象的内存对吗?问题是它没有。

谢谢你们的帮助:)。

编辑 1

我真的被卡住了......我删除了我的 NSMutableArray 中的所有对象,但 ARC 没有释放它们。有人帮忙吗?

谢谢

4

1 回答 1

0

那个似乎很明显。你把所有的粒子都存储在了_whiteParticlesArray,对吧?所以只要粒子还在那个数组中,它们就会被数组保留并保留在内存中。

当您在 Instruments 中删除所有对象并且内存使用量没有(显着)改变时,您可能还会遇到其他泄漏。您应该在 Instruments 中检查的一件事是有多少粒子对象是活着的。并且一定要验证场景实例本身在改变场景后被释放。

顺便说一句,提前创建数百个粒子系统并不是很有效。在需要时创建粒子时是否存在性能问题?如果没有,请即时创建它们。请记住,每个粒子系统本身使用大约 500 字节,因此 500 个粒子系统仅用于类实例就相当于大约 250 KB。

您仍然可以预加载纹理,这是最重要的部分。您需要做的就是创建使用嵌入纹理的每种粒子类型之一,或者使用纹理缓存来预加载没有嵌入纹理的粒子系统 plist 的纹理。

于 2013-05-28T22:48:35.340 回答