SCNPhysicsBody 的 SceneKit 的 collisionBitMask 属性的文档声明如下:

当两个物理实体相互接触时,可能会发生碰撞。 SceneKit 通过执行按位 AND 运算将主体的碰撞蒙版与其他主体的类别蒙版进行比较。如果结果是非零值,则主体受到碰撞的影响。 每个机构都独立地选择是否要受到另一个机构的影响.

最后一行表示如果我有两个对象,我可以将其设置为当它们发生碰撞时,只有其中一个应该受到碰撞的影响。

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 应该落在平面上,然后 sphere2 应该落在 sphere1 上并反弹,而 sphere1 应该不受与 sphere2 碰撞的影响。然而,观察到的行为是球体落在平面上并且彼此停留在内部 - 两个球体之间没有记录碰撞事件。

这里发生了什么?


在相关的注释中,当我对上面的代码进行一些小的修改时,会观察到一些甚至更奇怪的行为。

如果删除定义平面 collsionBitMask 的行,将其保留为默认 SCNPhysicsCollisionCategoryAll,则 sphere1 不再与平面发生碰撞。

如果我将定义对象的物理实体,categoryBitMasks 和 collisionBiMasks 的线移动到将对象添加到场景之后,则所有对象将与每个其他对象发生碰撞。即使我将每个 collisionBitMask 设置为零。