Как отладить Cocos2d удаление проблемы памяти спрайтов - PullRequest
1 голос
/ 06 марта 2012

Уже некоторое время работаю над игрой Tower Defense для iOS. Я использую Cocos2d (v0.99.5 не уверен). Недавно у меня начались проблемы с удалением спрайтов.

Есть профили с использованием инструментов и зомби, и вот что я получаю:

Zombie trace Код для обновления спрайтов (а также их удаления) находится в обновлении:

-(void) update:(ccTime)deltaTime {
if (paused)
    return;

CCArray *childs = [textureAtlas children];

//Update all objects
for (GameSprite *tempChar in childs) {
    if ([tempChar respondsToSelector:@selector(updateStateWithDeltaTime:andListOfGameObjects:andAtlas:)]) {
        [(GameSprite*)tempChar updateStateWithDeltaTime:deltaTime andListOfGameObjects:[textureAtlas children] andAtlas:textureAtlas]; 
    }
}

//Remove dead projectiles
for (GameSprite *tempChar in childs) {          
    if ([tempChar isKindOfClass:Projectile.class]) {  //(**)
        if (![tempChar alive]) {
            [tempChar remove];
        }
    }
}

//Remove dead towers
for (GameSprite *tempChar in childs) {
    if ([tempChar isKindOfClass:Tower.class]) {
        if (![tempChar alive]) {
            [tempChar remove];
        }
    }
}
//Remove dead creeps
for (GameSprite *tempChar in childs) {
    if ([tempChar isKindOfClass:Creep.class]) {
        if (![tempChar alive]) {
            [tempChar remove];
        }
    }
}
}

Метод удаления в GameSprite.m:

-(void)remove {
    CCLOG(@"remove");
    [self removeFromParentAndCleanup:YES];
}

Первый блок обновляет спрайты в SpriteBatchNode / textureAtlas. Три оставшихся блока проверяют различные объекты, если они должны быть удалены. (их живая переменная установлена ​​в NO?). Причина, по которой у меня три блока разных типов, связана с тем, что снаряды имеют (слабую) ссылку на ползучесть, по которой они стреляют, и должны быть удалены перед ползучестью.

Так что моя проблема в том, что он случайно падает, когда снаряд поражает крипа, и снаряд (и все другие снаряды, стреляющие в этого крипа) должны быть удалены). Счетчик ссылок Creeps уменьшается до 0, но, похоже, все еще находится в массиве childs. Причина ошибки, которую я получаю:

*** -[NormalProjectile isKindOfClass:]: message sent to deallocated instance 0xff33e30

в строке, которую я пометил (**)

Либо проблема заключается в том, что я понимаю, что у Cocos2d removeFromParentAndCleanUP, либо в том, что мое "решение" для обработки отношений projectile-creep-отношениях является плохим с точки зрения памяти. Любые идеи о том, как решить эту проблему или отладить ее дальше?

1 Ответ

3 голосов
/ 07 марта 2012

Ваши методы быстрого перечисления для прохождения массива приводят все ваши спрайты в этом массиве в качестве собственного подкласса CCSprite, а затем проверяют, не являются ли они другим пользовательским подклассом, таким как Tower, и т. Д. Я не вижу это как здоровая практика программирования, так как методы в одном классе не могут быть в другом, но вы, тем не менее, применяете их.

Это может или не может способствовать вашей проблеме, но более разумным подходом является сохранение assign iVar CCArray для детей определенного класса. т.е. поместите все ваши снаряды в один массив во время их создания и добавления в узел пакета , после чего вы можете перебирать все снаряды, башни и т. д., просматривая эти отдельные массивы, где вы знаете, какого рода класс они уже есть. Затем удалите их из массива, а также из родительского при необходимости. Я думаю, что это немного безопаснее, чем проходить через все игровые спрайты, входящие в ваш пакет, которые могут включать, возможно, неиспользуемые спиты, а также разыгрывать их и тестировать как разные классы.

...