1
votes

I want the bullet to collide with the ship but the func physicsWorld(_ world: SCNPhysicsWorld, didEnd contact: SCNPhysicsContact) is never called even though I set the delegate and physics body collision properties.

Here is my code:

class Bullet: SCNNode {
    override init () {
        super.init()
        let sphere = SCNSphere(radius: 0.020)
        sphere.materials.first?.diffuse.contents =  UIColor.red
        self.geometry = sphere
        let shape = SCNPhysicsShape(geometry: sphere, options: nil)
        self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: shape)
        self.physicsBody?.isAffectedByGravity = false
        self.physicsBody?.categoryBitMask = CollisionCategory.bullets.rawValue
        self.physicsBody?.contactTestBitMask = CollisionCategory.enemy.rawValue
        self.physicsBody?.collisionBitMask = CollisionCategory.enemy.rawValue
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

struct CollisionCategory: OptionSet {
    let rawValue: Int
    static let bullets  = CollisionCategory(rawValue: 1 << 1) // 00...01
    static let enemy = CollisionCategory(rawValue: 1 << 0) // 00..10
}
class ARViewController: UIViewController, ARSCNViewDelegate, SCNPhysicsContactDelegate {

    @IBOutlet var sceneView: ARSCNView!
    var enemyNodes = [SCNNode]()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set the view's delegate
        sceneView.delegate = self

        // Show statistics such as fps and timing information
        sceneView.showsStatistics = true
        sceneView.scene.physicsWorld.contactDelegate = self
       setupEnemies()

    }

func setupEnemies() {
        guard let enemyNode = SCNScene(named: "art.scnassets/ship.scn")?.rootNode.childNodes.first else { return }

        enemyNode.position = getRandomVector()
        enemyNode.name = "enemy"
        enemyNode.physicsBody?.categoryBitMask = CollisionCategory.enemy.rawValue
        enemyNode.physicsBody?.contactTestBitMask =  CollisionCategory.bullets.rawValue
        enemyNode.physicsBody?.collisionBitMask = CollisionCategory.bullets.rawValue
        enemyNodes.append(enemyNode)
        sceneView.scene.rootNode.addChildNode(enemyNode)
    }

func physicsWorld(_ world: SCNPhysicsWorld, didEnd contact: SCNPhysicsContact) {
        print("did begin contact", contact.nodeA.physicsBody!.categoryBitMask, contact.nodeB.physicsBody!.categoryBitMask)
}
}

I don't know where I am going wrong.

1
Have you set physicsBody for the ship node? Make sure it's not nil.M Reza
Wow thanks buddy!! That was a silly mistake from my side.Sharmin Khan

1 Answers

1
votes

I had not set the physicsBody for the enemy node as pointed out by Mo Reza. All I had to do was:

self.physicsBody = SCNPhysicsBody(type: .static, shape: nil)

and it worked.