0

The documentation for SceneKit's collisionBitMask property of SCNPhysicsBody states the following:

When two physics bodies contact each other, a collision may occur. SceneKit compares the body’s collision mask to the other body’s category mask by performing a bitwise AND operation. If the result is a nonzero value, then the body is affected by the collision. Each body independently chooses whether it wants to be affected by the other body.

That last line indicates that if I have two objects, I can set it up so that when they collide, only one of them should be affected by the collision.

let CollisionCategoryPlane = 1 << 0
let CollisionCategorySphere1 = 1 << 1
let CollisionCategorySphere2 = 1 << 2

let plane = SCNNode(geometry: SCNPlane(width: 10, height: 10))
plane.position = SCNVector3(x: 0, y: -10, z: 0)
plane.eulerAngles = SCNVector3(x: Float(-M_PI/2), y: 0, z: 0)
plane.physicsBody = SCNPhysicsBody.staticBody()
plane.physicsBody?.categoryBitMask = CollisionCategoryPlane
plane.physicsBody?.collisionBitMask = CollisionCategorySphere1 | CollisionCategorySphere2 
// the plane should be affected by collisions with both spheres (but the plane is static so it doesn't matter)
scene.rootNode.addChildNode(plane)

let sphere1 = SCNNode(geometry: SCNSphere(radius: 1))
sphere1.physicsBody = SCNPhysicsBody.dynamicBody()
sphere1.physicsBody?.categoryBitMask = CollisionCategorySphere1
sphere1.physicsBody?.collisionBitMask = CollisionCategoryPlane 
// sphere1 should only be affected by collisions with the plane, not with sphere2
scene.rootNode.addChildNode(sphere1)

let sphere2 = SCNNode(geometry: SCNSphere(radius: 1))
sphere2.position = SCNVector3(x: 1, y: 10, z: 0)
sphere2.physicsBody = SCNPhysicsBody.dynamicBody()
sphere2.physicsBody?.categoryBitMask = CollisionCategorySphere2
sphere2.physicsBody?.collisionBitMask = CollisionCategoryPlane | CollisionCategorySphere1 
// sphere2 should be affected by collisions with the plane and sphere1
scene.rootNode.addChildNode(sphere2)

Sphere1 should fall onto the plane, then sphere2 should fall onto sphere1 and bounce off, and sphere1 should be unaffected by the collision with sphere2. However, the observed behaviour is both spheres falling onto the plane and coming to rest inside each other - no collision event between the two spheres is registered.

What is going on here?


On related notes, some even stranger behaviour is observed when I make a couple small modifications to the above code.

If remove the line that defines the plane's collsionBitMask, leaving it as the default SCNPhysicsCollisionCategoryAll, sphere1 no longer collides with the plane.

If I move the lines that define the objects' physics bodies, categoryBitMasks, and collisionBiMasks to after the objects have each been added to the the scene, all the objects will collide with every other object. Even if I set every collisionBitMask to zero.

David Bagwell
  • 318
  • 3
  • 12
  • first sphere doesn't include categorysphere2 in its collision mask. Those bitmasks have to match both ways, ie body A category must be in collision maks of body B, and body B category must be in collision mask of body A. – CodeSmile Jan 12 '15 at 17:51
  • But if they always have to match both ways, then it would never be possible for a collision to only affect one of the bodies. "Each body independently chooses whether it wants to be affected by the other body". To me, that implies that a collision has the possibility of affecting one body but not the other. – David Bagwell Jan 12 '15 at 18:05
  • how should that work? Body A decides it can pass through body B, but body B decides it can not pass through A. Who wins? Schizophrenia. ;) – CodeSmile Jan 12 '15 at 22:33
  • There's an example in my expected behaviour of the code in the question. The bodies don't pass through each other, because at least one of them is affected by the collision. Sphere2 bounces off sphere1 because it decides to be affected by the collision, but sphere1 stays where it is because it decides not to. The example in the chosen answer to [this question](http://stackoverflow.com/questions/27372138/how-to-set-up-scenekit-collision-detection) uses the same logic. – David Bagwell Jan 12 '15 at 23:46
  • yeah but if you want both bodies to collide the table test in said question has to match both ways - you *have* to set it up so that both can collide with each other if you want them to collide with each other. This is necessary because in your current setup it would be ambiguous whether these bodies should collide or not, depending on whether you consider sphere1 or sphere2's perspective - so they don't collide by definition of the physics engine in order to avoid such ambiguity. – CodeSmile Jan 13 '15 at 19:07
  • The example in said question mentions missiles affecting rockets and asteroids, but not the other way around. What I'm trying to point out is that the way the documentation is worded, it should be allowed to be ambiguous. From sphere1's perspective there is no collision, from sphere2's there is. If that's not the case then the documentation is worded wrong. Should it instead say "Both bodies involved in the collision must mutually agree to be affected by the other body."? – David Bagwell Jan 13 '15 at 19:49
  • the wording here is indeed misleading. check skphysicsbody docs, it has the same properties and works the same way, perhaps the docs there are more clear about that – CodeSmile Jan 14 '15 at 07:22

0 Answers0