[WINDOWS] v3.7 setPhysicsBody() causes Sprite to disappear if added from collision callback?

This looks like it might be a bug.

I have some code called from the onContactBegin() physics callback that causes some sprites with physicsbodies attached to be added to the layer. The sprites and the physicsbodies do not appear now unless I add a scheduled function to add them after a small amount of time, say 1/60 of a second. They are added no problem if I create them outside of the collision callback function.

Anyone else seeing this?

Are you allocating the sprites in the onContactBegin event?

For physics engines in general (at least for Box2d and Chipmunk), the collision callbacks should only be used to set flags or do other very efficient tasks.

In general you probably shouldn’t be doing time consuming tasks like allocating a sprite.

With that said, Cocos2d-x might be doing something different that the Chipmunk collision detection: https://github.com/cocos2d/cocos2d-x/issues/13278
But it might be changed in the future to use the more efficient built in Chipmunk collision detection if it is not already.

Same issue here. But I am not allocating the sprites inside onContactBegin(). Nobody gave me a proper answer is like the engine simply doesn’t like me.

@Heyalda Yes I am allocating sprites in functions called from onContactBegin, but this worked fine with no problems in versions before 3.7 so I’m wondering if this is some kind of newly-introduced bug. Thanks for the tip about not doing time-consuming tasks in the collision callback, but in that case is it better to schedule such things to take place outside of that function?

Basically I’m using it to detect when the player’s projectile has hit an asteroid. If it has, I call a destroy() method on the asteroid object which then spawns three smaller ones (allocating sprites). Is there a better approach for when to call destroy? Like I said I’ve changed it to avoid this disappearing issue by scheduling destroy() for 1/60 second later, rather than the method getting called directly from onContactBegin().

Cheers :smile:

You might want to allocate a pool of sprites and retain them so that you are not allocating new sprites when the exposition occurs. If the smaller sprites also need physics, then it gets more complicated.

std::vector <Asteroid*> _needToExplodeAsteroids;

Maybe you could use a C++ vector of pointers to asteroid objects called _needToExplodeAsteroids in your class that has the onContactBegin. Then in onContactBegin you could push the pointer of the asteroid onto that vector.

Then in the update function of that class, you could check the size of _needToExplodeAsteroids and if it has any elements, then cycle through them and process the Asteroids.

This way, it is always the next frame update that the asteroid gets destroyed.

Thanks Heyalda, I was thinking that I’d need to flag each asteroid to be destroyed then test them all each frame which would be inefficient, but a vector makes perfect sense :smile: