cocos2d-x v3.0에서 Box2D사용할 때 리소스 관리 b2Body 객체의 소멸 시점 지정

cocos2d-x v3.0는 스프라이트가 화면 밖으로 나가면 스프라이트의 소멸이 자동적으로 된다. 반면에 Box2d라이브러리를 cocos2d-x에서 쓰게되면 객체가 화면밖으로 나갔을때 스프라이트는 자동적으로 없어지지만 Box2D Body의 경우는 그대로 존재한다. 하나의 레이어에서 오랜 시간 게임을 하게 될 때 이런 객체들이 쌓여 렉을 유발 할 수 있다.


254

366


verts가 336으로 늘었다. 여기서는 debug모드로 Body만 그린다. 


모든 Body를 화면 밖으로 밀어냈지만 GL verts의 수는 줄지 않았다.

주기적인 검사로 Body의 위치를 확인하고 화면 밖으로 나가는 경우 Body를 소멸 시켜야 한다.

cocos2d-x지만 Box2d의 Testbed에서 사용하는 경우도 기본 소스는 마찬가지다.


tick 함수는 cocos2d 의 스케줄러에 사용할 콜백함수를 만든 것이다.

코코스 내부적인 스케줄러가 있다면 Box2d에서는 Step 함수가 그것이다.

Box2d의 Testbed를 사용한다면 Test::Step(Setting settings)를 오버라이딩 하면된다. 이 때 주의점은 Test::Step();를 먼저 호출한 뒤 오버라이딩 해야 한다.

위에서 break;를 써줌으로써 한번의 콜에 하나의 객체만 소멸된다. 만약 break;를 하지 않는다면 if문 내부에서 객체를 소멸한 후  b=_world->GetBodyList();를 다시 호출 해야 한다. 안그러면 Body 리스트내에 소멸된 객체의 공백이 생겨서(b가 NULL포인터를 가리키게 됨으로) b->GetNext()에서 에러가 나게 된다. NULL->GetNext()는 말이 되지 않기 때문이다. 개인적인 생각으로는 break;를 사용하는 것이 자연스럽다. 많은 b2Body가 동시 다발적으로 외부로 나가는 경우(예를들어 슈팅게임에서 총알) 스케줄러의 한번 호출에 소멸 시켜야 할 b2Body가 많을 경우 필요 이상의 렉이 발생할 수 있기 때문이다. 이 경우 외부로 나가버린 b2Body를 모두 소멸 시킬 때 까지 tick함수는 리턴하지 않기 때문이다. 콜은 주기적으로 이루어지기 때문에 한번의 콜에 한개의 객체를 삭제하는 것이 바람직하다.




그럼 위 처리를 한 후 같은 실행을 해보겠다.


20개의 b2Body 생성





10개의 b2Body를 화면 밖으로 던짐



1개의 b2Body는 8이므로 80이 줄었다.

물론 debug모드로 실제 프로젝트를 생성할 일은 없겠지만, 게임을 만드는 과정에서 복잡한 게임의 경우 디버그 모드가 렉을 유발할 때 이런 간단한 처리로 객체를 관리할 수 있다.

이 댓글을 비밀 댓글로