2012-03-06 2 views
1

iOS 용 타워 디펜스 게임을 당분간 사용 해왔다. Cocos2d (v0.99.5 확실하지 않음)를 사용하고 있습니다. 최근 스프라이트 제거를 시작할 때 몇 가지 문제가 발생하기 시작했습니다.스프라이트 메모리 문제의 Cocos2d 제거를 디버그하는 방법

악기와 좀비를 사용하여 프로파일을 가지고 여기에 내가 무엇을 얻을 :

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에서 스프라이트를 업데이트합니다. 세 개의 나머지 블록은 삭제해야 할 다른 객체를 검사합니다. (그들의 alive-variable을 NO로 설정)? 세 가지 유형의 블록이있는 이유는 발사체가 (약한) 크립에 대한 참조를 가지고 있기 때문입니다. 크립이 발생하기 전에 삭제해야합니다.

내 문제는 발사체가 크립을 치고 프로 기어 (그리고 그 크립에서 발사하는 다른 모든 발사체)를 제거 할 때 무작위로 충돌한다는 것입니다. 크립 참조 수는 0으로 떨어지지 만 여전히 하위 배열에있는 것으로 보입니다. 원인 이해가 오류가 있습니다 : 나는 (**)

로 표시된 행에

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

어느 쪽의 문제는 나를적인 Cocos2D의 removeFromParentAndCleanUP을 이해하는 것입니다 : 또는 발사체-크리프을 처리하기위한 내 "솔루션" - 관계는 기억의 관점에서 나쁘다. 이 문제를 해결하거나 디버깅하는 방법에 대한 아이디어가 있습니까?

답변

3

어레이를 통과하기위한 빠른 열거 기법은 해당 배열의 모든 스프라이트를 CCSprite의 사용자 정의 서브 클래스로 캐스팅 한 다음 타워와 같은 다른 사용자 정의 서브 클래스인지 확인합니다. 하나의 클래스에있는 메소드가 다른 클래스에 없기 때문에 건강한 프로그래밍 실습으로 보아라. 그럼에도 불구하고 당신은 그것들을 캐스팅한다.

그게 문제가 될 수도 있고 아닐 수도 있지만 더 현명한 접근 방법은 특정 클래스의 아이들을 위해 assign iVar CCArray를 유지하는 것입니다. 즉, 모든 발사체를 하나의 배열 에 넣고 배치 노드에 추가하면 모든 발사체, 타워 등을 반복 할 수 있습니다. 각 발사체는 이미 어떤 종류의 클래스인지 알고 있습니다. . 그런 다음 필요한 경우 부모뿐만 아니라 어레이에서도 제거하십시오. 아마도이 게임은 사용하지 않는 spites를 포함하여 batchnode에있는 모든 게임의 스프라이트를 거치면서 캐스팅하고 다른 캐스팅으로 테스트하는 것보다 훨씬 안전하다고 생각합니다.

+0

감사합니다. 3 개의 새로운 배열을 생성하고이를 통해 열거함으로써이를 해결했습니다. 이것을 건너 뛰고 싶었지만 textureAtlas의 자식을 반복하는 것이 안전한 방법은 아닙니다. – Sunkas

+0

더 안전한 기술을 사용하여 효과가 있음을 확인하는 것이 좋습니다. 정말 올바른 접근 방식입니다. – johnbakers

관련 문제