1
votes

I have a problem with the way SpriteKit resolves collisions between two bodies. I am developing a game in which sprite nodes are dynamically added to the screen at random positions. All of those sprites have physics bodies that collides with each other. On higher game levels there are a lot of those sprites and sometimes new sprite it added on top of another one (which is correct behavior as long as collision is resolved smoothly). In Cocos2d + Box2d in this situation collision is resolved smoothly. Both sprites are gently moved in opposite directions until they don't collide anymore. It looks pretty well, even if there is a lot of such collisions, the movement animations is smooth and FTP is high. However, on SpireKit things looks a little bit different. When new body is added on top of another one, from user point of view it's not moved to resolve collision - it's "teleported" instead. There is no smooth movement of spires, they just being re-positioned in the way that they won't collide anymore. It looks pretty bad for the player, even the game runs 60 frames per second. I read in Apple documentation:

A collision is used to prevent two objects from interpenetrating each other. When one body strikes another body, Sprite Kit automatically computes the results of the collision and applies impulse to the bodies in the collision.

But it doesn't look like it happens as described. Apple tells me that when collision occurs there will be an impulse applied to the bodies that collides with each other, but in real life it looks like the bodies are "teleported" (instantly moved in the place that doesn't trigger collision anymore). Maybe the force applied to the bodies is so strong, that you can't see objects movement. I wonder if there is a way to improve such behavior in SpriteKit, so it looks more like in Cocos2d + Box2d. The Apple's SpriteKit is based on Box2d after all.

2
Please let me know if you figure out any updates on this. It doesn't seen to have changed and every now and then my game will have a little "jitter" and my player will teleport because of the same reason.datWooWoo
I didn't found any solution, but for a workaround I modified the logic behind adding sprites to scene, so they won't overlap. Nothing special, but works in my case.Darrarski

2 Answers

1
votes

Actually overlapping bodies is not a behavior physics engines try to model or have incorporated into their design as a feature - the observed behavior is merely a side-effect, and possibly heavily influenced by the body's parameters (definitely by "bullet" or "continuous" collision detection, usesPreciseCollisionDetection in Sprite Kit terms).

In a rigid body physics engines such as Box2D, two overlapping bodies is something the physics engine strives to avoid. The speed at which it does so - iteratively over several frames or (near) instantaneous - could be specific property of the physics engine respetively the settings with which it is initialized internally.

The "soft" way you describe can actually be very problematic for regular collision resolve. Especially if bodies are designed to be rigid, ie a player body must not penetrate a wall or the floor even just a little bit. It makes sense for Sprite Kit to try and avoid that behavior altogether, it's usually more problematic than helpful or desirable.

So the answer is: try different variations of parameters to see if you can get the desired behavior. But I wouldn't be surprised if two overlapping bodies that slowly move apart isn't actually possible in Sprite Kit. That is unless the bodies simply don't have enough room to move completely apart.

1
votes

I found a solution in my case. Unfortunately my situation might be different.

For me, my problem was that when there were more than one Physical Body contacting the players physical body, it would teleport the player. In my game, when the player grabbed a collectible item right at the moment an attack hits the player and is overlapping him (so both the collectible and attack physical bodies are overlapping the players physical body) it would teleport the player. This was even with collisionBitMask = 0 for all of them.

I was able to organize the contactBitMasks in such a way that 2 contacts were not being registered for 2 things at once from the same Sprite. That's hard to explain without an example:

Note: collisionBitMask = 0 for all of them (the player only collided with the ground)

What I had before:

Player

contactBitMask = Attack | Collectible

Attack

contactBitMask = 0

Collectible

contactBitMask = 0

What fixed it:

Player

contactBitMask = Attack

Attack

contactBitMask = 0

Collectible

contactBitMask = Player

After changing it to the above, nothing teleports and the physical bodies can overlap with nothing going wrong.