1
votes

I'm trying to build a game using ARkit and SceneKit, but after setting up the physicsWorld delegate and the physics body of the objects, the delegate method didBeginContact is not called.

This is my struct for physics body

struct CollisionCategory {
    static let moltenBullet :Int = 4
    static let iceShield :Int = 8
}

this is how I set the physics body

 let collisionShape = SCNPhysicsShape(node: node, options: nil)
        self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: collisionShape)
        self.physicsBody?.categoryBitMask = self.categoryMask
        self.physicsBody?.contactTestBitMask = self.collisionMask
        self.physicsBody?.collisionBitMask = self.collisionMask

I use self because it is the physics body of a custom class that inherit from SCNNode, collisionMask and categoryMask are setted in the constructor using the struct above.

In the didBeginContact I want to print something but nothing happens. I already setted the SCNPhysicsContactDelegate to

sceneView.scene.physicsWorld.contactDelegate

sceneView is ARSCNView.

I correctly see the shape of the physicsBody with

SCNDebugOptionShowPhysicsShape

Why is this happening ?

1
Do you expect two objects with the same CollisionCategory or a bullet and the shield to collide?jlsiewert
The object are declared in this way object1(category: object1, collision: object2), object2(category: object2, collision: object1)Andrew21111
Sorry, Yes ! I expect that a bullet and the shield collideAndrew21111

1 Answers

3
votes

Your nodes don't interact with each other because they are in different categories. Here is how the collsionBitMask works according to the documentation:

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.

The contactBitMask and categoryBitMask work the same.

When SceneKit checks your physicsBody for a contact this is what happens:

object1.physicsBody.contactTestBitMask = 4 = 0100b
object2.physicsBody.categoryBitMask    = 8 = 1000b
                                             -----
                               (bitwise AND) 0000b = 0 -> no collision

The best way to define your categories is with an OptionSet, Apple actually provides you with default categories in SCNPhysicsCollisionCategory.

If you want two nodes or physicsBody's to interact they need to share at least one category. Otherwise they will not collide.

Here is how your example should probably look like:

struct CollisionCategory: OptionSet {
    let rawValue: Int

    static let moltenBullet = CollisionCategory(rawValue: 4)
    static let iceWall = CollisionCategory(rawValue : 8)
}

Then you assign your categories like this:

class Bullet: SCNNode {
    ...

    // The physics body-category is a bullet
    self.physicsBody?.categoryBitMask = CollisionCategory.moltenBuller.rawValue
    // This contacts with both other bullets and ice walls!
    self.physicsBody?.contactBitMask = [CollsionCategory.moltenBullet, CollisionCategory.iceWall].rawValue
    self.physicsBody?.collisionBitMask = self.physicsBody!.contactBitMask
 }