しばらくの間、iOSのタワーディフェンスゲームで作業していました。私はCocos2dを使用しています(v0.99.5はわかりません)。最近、スプライトの削除を開始したときにいくつかの問題が発生し始めました。スプライトメモリの問題をCocos2dで取り除く方法をデバッグする方法
は楽器やゾンビを使用してプロファイルを持っているし、ここで私が得るものです:
コードを(してもそれらを削除)更新に位置してスプライトを更新するために:
-(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];
}
}
}
}
removeメソッドでGameSprite.m:
-(void)remove {
CCLOG(@"remove");
[self removeFromParentAndCleanup:YES];
}
最初のブロックはSpriteBatchNode/textureAtlasにスプライトを更新します。 3つの残りのブロックは、削除すべきオブジェクトがあるかどうかをチェックします。 (それらのalive-variableはNO?に設定されています)。私が異なるタイプのブロックを3つ持っている理由は、発射体が(弱い)射撃を参照しているため、射撃の前に削除する必要があるからです。
私の問題は、発射物がクリープに当たってプロジェクタイル(およびそのクリープで射撃する他のすべての発射体)を取り除くときにランダムにクラッシュすることです。クリープ参照カウントは0になりますが、まだチャイルド配列内にあるようです。原因私が手にエラーがある:私は(**)
でマークされた行の
*** -[NormalProjectile isKindOfClass:]: message sent to deallocated instance 0xff33e30
どちらの問題は私がCocos2dのremoveFromParentAndCleanUPを理解することである:またはその弾丸クリープを処理するための私の「ソリューション」 - 記憶の観点から、関係は悪いです。どのようにこれを解決するか、それをさらにデバッグするためのアイデア?
ありがとうございました。 3つの新しい配列を作成し、それらを列挙して解決しました。これをスキップすることを望んでいましたが、textureAtlasの子を反復処理するのは安全な方法ではありません。 – Sunkas
安全なテクニックを使って解決したことは素晴らしいことです。それは本当に正しいアプローチです。 – johnbakers