【问题标题】:How to debug Cocos2d removal of sprite memory issue如何调试Cocos2d去除精灵内存问题
【发布时间】:2012-03-24 06:57:35
【问题描述】:

从事 iOS 版塔防游戏已经有一段时间了。我正在使用 Cocos2d(不确定 v0.99.5)。最近开始删除精灵时遇到了一些问题。

拥有使用仪器和僵尸的个人资料,这就是我得到的:

更新精灵(以及删除它们)的代码位于 update:

-(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 中的 remove 方法:

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

第一个块更新 SpriteBatchNode/textureAtlas 中的精灵。剩下的三个块检查不同的对象是否应该被删除。 (他们的活动变量设置为否?)。我有三种不同类型的方块的原因是因为射弹对它们射击的小兵有(弱)参考,需要在小兵之前删除。

所以我的问题是,当弹丸击中小兵并且要移除弹丸(以及向该小兵射击的所有其他弹丸)时,它会随机崩溃)。爬虫引用计数降至 0,但似乎仍在 childs 数组中。因为我得到的错误是:

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

在我用 (**) 标记的那一行

问题要么是我理解 Cocos2d 的 removeFromParentAndCleanUP: ,要么是我处理弹丸-蠕变关系的“解决方案”从记忆的角度来看是不好的。有关如何解决此问题或进一步调试的任何想法?

【问题讨论】:

    标签: ios memory-leaks cocos2d-iphone nszombies


    【解决方案1】:

    您用于遍历数组的快速枚举技术是将该数组中的所有精灵转换为 CCSprite 的自定义子类,然后检查它们是否是不同的自定义子类,例如 Tower 等。我没有看到这是一种健康的编程实践,因为一个类中的方法可能不在另一个类中,但您仍然在强制转换它们。

    这可能会或可能不会导致您的问题,但更明智的方法是为特定班级的孩子保留assign iVar CCArray。即把你所有的射弹放在一个数组中在它们被创建并添加到批处理节点时然后你可以通过遍历这些单独的数组来迭代所有的射弹、塔等,在那里你知道什么类型他们已经是一流的了。然后在必要时将它们从数组和父级中删除。我认为这比完整浏览您的批处理节点中的所有游戏精灵要安全得多,其中可能包括未使用的恶意,以及将它们转换为不同的类并对其进行测试。

    【讨论】:

    • 谢谢。通过创建三个新数组并枚举它们来解决它。希望跳过这个,但似乎遍历 textureAtlas 的孩子并不是一种安全的方法。
    • 很高兴听到它使用更安全的技术解决了问题。这确实是正确的方法。
    猜你喜欢
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多