Understanding Spritekit Collisionbitmask

How does collisionBitMask work? Swift/SpriteKit

You can't get desired behaviour because you haven't set category, contact and collision bit masks properly. Here is an example on how you can set this to work:

greenBall.physicsBody?.categoryBitMask = GreenBallCategory //Category is GreenBall
greenBall.physicsBody?.contactTestBitMask = RedBarCategory | WallCategory //Contact will be detected when GreenBall make a contact with RedBar or a Wall (assuming that redBar's masks are already properly set)
greenBall.physicsBody?.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory //Collision will occur when GreenBall hits GreenBall, RedBall or hits a Wall

redBall.physicsBody?.categoryBitMask = RedBallCategory //Category is RedBall
redBall.physicsBody?.contactTestBitMask = GreenBarCategory | GreenBallCategory | WallCategory //Contact will be detected when RedBall make a contact with GreenBar , GreenBall or a Wall
redBall.physicsBody?.collisionBitMask = RedBallCategory | GreenBallCategory | WallCategory //Collision will occur when RedBall meets RedBall, GreenBall or hits a Wall

let borderBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
self.physicsBody = borderBody
self.physicsBody?.friction = 0
borderBody.contactTestBitMask = RedBallCategory | GreenBallCategory //Contact will be detected when red or green ball hit the wall
borderBody.categoryBitMask = WallCategory
borderBody.collisionBitMask = RedBallCategory | GreenBallCategory // Collisions between RedBall GreenBall and a Wall will be detected

I would recommend you to read docs about categoryBitMask which is a mask that defines which categories a physics body belongs to:

Every physics body in a scene can be assigned to up to 32 different
categories, each corresponding to a bit in the bit mask. You define
the mask values used in your game. In conjunction with the
collisionBitMask and contactTestBitMask properties, you define which
physics bodies interact with each other and when your game is notified
of these interactions.

contactTestBitMask - A mask that defines which categories of bodies cause intersection notifications with a current physics body.

When two bodies share the same space, each body’s category mask is
tested against the other body’s contact mask by performing a logical
AND operation. If either comparison results in a nonzero value, an
SKPhysicsContact object is created and passed to the physics world’s
delegate. For best performance, only set bits in the contacts mask for
interactions you are interested in.

collisionBitmask - A mask that defines which categories of physics bodies can collide with this physics body.

When two physics bodies contact each other, a collision may occur.
This body’s collision mask is compared to the other body’s category
mask by performing a logical AND operation. If the result is a nonzero
value, this body is affected by the collision. Each body independently
chooses whether it wants to be affected by the other body. For
example, you might use this to avoid collision calculations that would
make negligible changes to a body’s velocity.

So basically, to set up all these, you should ask your self something like:

Okay, I have a green ball, and a red ball , and wall objects on the scene. Between which bodies I want collisions to occur, or when I want to register contacts? I want a green and a red ball to collide with each other and to collide against the walls. Not a problem. I will first set up categories properly, and then I will set collision bit masks like this:

greenBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory; //greenBall will collide with greenBall, redBall and a wall
redBall.collisionBitMask = GreenBallCategory | RedBallCategory | WallCategory

wall.collisionBitMask = GreenBall | RedBall

Now, I want to detect when some contacts occur (in didBeginContact: method)... But I don't want to get notified about all possible contacts, but rather to be notified just about contacts between balls (contacts between balls and a wall will be ignored). So lets set contactTestBitMasks to achieve this:

greenBall.contactTestBitMask = GreenBallCategory | RedBallCategory;
redBall.contactTestBitMask = GreenBallCategory | RedBallCategory;

And that's it. The important thing is when you not using contact detection, you should not set contactTestBitMask. This is because of performance reasons. If you don't need collision detection, and you are interested only in detecting contacts, you can set collisionBitMask = 0.

Important:

Make sure you have set physics world's contact delegate in order to use didBeginContact and didEndContact methods:

self.physicsWorld.contactDelegate = self; //where self is a current scene

Hope this helps a bit.

collisionBitMask values not working in SpriteKit

You are overwriting collisionBitMask when you set it up for the second time. You should set up an OR bitmask with the symbol |.

Replace

self.physicsBody?.collisionBitMask = UInt32(PhysicsCategory.Obstacle)
self.physicsBody?.collisionBitMask = UInt32(PhysicsCategory.Ground)

with:

self.physicsBody?.collisionBitMask = UInt32(PhysicsCategory.Obstacle) | UInt32(PhysicsCategory.Ground)

and

self.physicsBody?.collisionBitMask = UInt32(PhysicsCategory.Player)
self.physicsBody?.collisionBitMask = UInt32(PhysicsCategory.Ground)

with:

self.physicsBody?.collisionBitMask = UInt32(PhysicsCategory.Player) | UInt32(PhysicsCategory.Ground)

How does the category bit mask work in SpriteKit?(0xFFFFFFFF)

Categories

You can have 32 different categories. Categories could be vessel, bullets, wall, enemies, etc). If you are interested in collisions and contacts then you need first to set a category for a given objet. For example, vessel category 0, bullets category 1, wall category 2, enemies category 3. As they are bitmask then you have (respectively) 1, 2, 4, 8.
Now categories are more a matter of behavior than identity. Some objects may behave like two different categories: rocks (no category per-se) behave like walls (you bounce on it) and enemies (you can throw bullet at them). Then the categories for rocks would be 2 and 3, as bit mask this give 12. It is not easy to imagine that an object is in different categories, but if you think about behavior sets and not identity sets, that ease to think about it.

Default value for masks are 0xFFFFFFFF meanings that every object is in every possible category and every object collides with every other.
Fine tuning these values can seriously improve the physical engine.

Collisions

Collisions are used to define which objects collides in the physical world. Some objects may cross to each other while other bounce. Example: a magical bullet may travel walls, while ordinary ones are stopped at walls.

magicBullet.physicsBody.categoryBitMask = 1
ordinaryBullet.physicsBody.categoryBitMask = 1 // both bullets behave as bullets
wall.physicsBody.categoryBitMask = 2

ordinaryBullet.physicsBody.collisionBitMask = 2 // hits walls
magicBullet.physicsBody.collisionBitMask = 0 // do not physically see walls

Collisions are declared as bit masks because you have to declare which other category a given object is able to physically interact with or not.

Contacts

Contacts are exactly the same as collisions but to capture in your code the fact that two objects are in contact. So if you are interested in ordinary bullets hitting a wall (for magical it is not necessarily interesting):

ordinaryBullet.physicsBody.contactTestBitMask = 2 // want to catch wall hit
magicBullet.physicsBody.contactTestBitMask = 0 // don't bother

A slightly more complex example

Now if you add another kind of object say hard wall, that could give:

magicBullet.physicsBody.categoryBitMask = 1
ordinaryBullet.physicsBody.categoryBitMask = 1 // both bullets behave as bullets
wall.physicsBody.categoryBitMask = 2 // some bullets may travel through
hardWall.physicsBody.categoryBitMask = 4 // nothing can travel through thses

ordinaryBullet.physicsBody.collisionBitMask = 6 // hits walls and hard walls
magicBullet.physicsBody.collisionBitMask = 4 // do not physically see walls but only hard walls

ordinaryBullet.physicsBody.contactTestBitMask = 6 // want to catch all wall hit
magicBullet.physicsBody.contactTestBitMask = 4 // just want to catch hard wall hitting

Can't understand how collision bit mask works

That is not how collision handling works. When two bodies are in intersection, physics engine performs logical AND operator between current's body collisionBitMask and other's body categoryBitMask:

When two physics bodies contact each other, a collision may occur.
This body’s collision mask is compared to the other body’s category
mask by performing a logical AND operation. If the result is a nonzero
value, this body is affected by the collision. Each body independently
chooses whether it wants to be affected by the other body. For
example, you might use this to avoid collision calculations that would
make negligible changes to a body’s velocity.

The source.

So the result depending on how you set categoryBitMask on those two bodies. A default value for categoryBitMask is 0xFFFFFFFF, means all bits set. So when you perform & between 0xFFFFFFFF and 0b10 or 0b01, the result would be non-zero value, thus the collision.

So for example, setting your bodies like this:

spriteA.physicsBody?.categoryBitMask = 0b01
spriteA.physicsBody?.collisionBitMask = 0b01

and

spriteB.physicsBody?.categoryBitMask = 0b10
spriteB.physicsBody?.collisionBitMask = 0b10

will give you the result you want. Also, this is probably not the exact setup you need, it is just a simple example, and you will have to change values according to your needs. In this case, spriteA will collide only with bodies which have categoryBitMask set to 0b01. Same goes for spriteB, it will collide with bodies which have categoryBitMask set to 0b10.

Also, in the case if you don't want these sprites to be able to collide with anything, simply set their collisionBitMask properties to 0.

Swift Sprite kit Collision Bitmask

You are not understanding how didBeginContact works. Basically what is happening is when any 2 nodes make a contact, the first thing that the system will do is make sure that the category and contact bit masks line up to make a valid contact. If it does, then didBeginContact gets called. now inside this function, you have the 2 arbitrary nodes that made contact, called bodyA, and bodyB. What you need to do first, is figure out what bodyA and bodyB are. So the first thing you do, is check the categoryBitMask.

   if(contact.bodyA.categoryBitMask == HERO) then contact.bodyA is a hero

Now that we know what categories these nodes refer to, we can then check what the node actually is. To do this, you can either check the name of the node

  if(contact.bodyA.node.name == "Hero") then bodyA is the hero 

Or compare the node itself

  if(contact.bodyA.node == heroNode) then bodyA is the hero

Now do the same for bodyB.

You have established at this point what your nodes are, you can proceed with the outcome results that you need based on this information.

If Hero hits both enemy nodes at the same time, then you need to handle this as well. What is going to happen is 2 calls to didBeginContact will happen, you need to find a way to remember this, and do your contact code in either the didEvaluateActions, or didSimulatePhysicsMethod. I do not remember which of these follows didBeginContact, so you will have to test it out on your own.

Using SKPhysics body for detecting collisions

The bullet is ‘moving around’ the player instead of through it because you have collisions turned on. All physics bodies collide with all others by default, whereas by default there are no contacts registered between physics bodies.

The first thing to do is to turn off collisions between the player and the bullet and vice-versa whilst leaving all other collisions unaffected:

playerNode.physicsBody?.collisionBitMask &= ~physicsCategory.bullet
bullet.physicsBody?.collisionBitMask &= ~physicsCategory.player

Edit: my step-by-step guide for collisions and contacts:
https://stackoverflow.com/a/51041474/1430420

A guide to collision and contactTest bit masks:
https://stackoverflow.com/a/40596890/1430420

Manipulating bit masks to turn individual collisions and contacts off and on.
https://stackoverflow.com/a/46495864/1430420

collisionBitMask doesn't work

If I understood correctly, you want the player and the NPC to "bounce off the walls", but not bounce off each other. The solution would be to not set their collisionBitMasks to each other‘s categoryBitMasks, but only their contactTestBitMasks.

As to why the NPC needs to be dynamic to bounce off the walls: One participant must be dynamic for a collision to show effect: the one that bounces off.



Related Topics



Leave a reply



Submit