しばらくの間、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 内のスプライトを更新します。残りの 3 つのブロックは、さまざまなオブジェクトを削除する必要があるかどうかをチェックします。(彼らの生きている変数は NO に設定されていますか?)。私が異なるタイプの 3 つのブロックを持っている理由は、発射体がクリープを (弱い) 参照しており、クリープの前に削除する必要があるためです。
したがって、私の問題は、発射体がクリープに衝突し、発射体(およびそのクリープを発射する他のすべての発射体)が削除されると、ランダムにクラッシュすることです。クリープの参照カウントは 0 になりましたが、まだ子配列にあるようです。エラーの原因は次のとおりです。
*** -[NormalProjectile isKindOfClass:]: message sent to deallocated instance 0xff33e30
(**) でマークした行に
問題は、Cocos2d の removeFromParentAndCleanUP: を理解することであるか、または発射物とクリープの関係を処理するための私の「解決策」がメモリの観点から悪いことです。これを解決する方法やさらにデバッグする方法についてのアイデアはありますか?