Search code examples
swiftsprite-kitcollision-detectionskphysicsbody

Swift SpriteKit Collisions Registered Multiple Times


I'm using SpriteKit and Swift to build an iPhone game, and my collision detection system is not functioning as I want it to. When my "bullet" physics body and my "player" physics body collide, the collision detection function is being called multiple times, usually 4-12 times. I have tried setting "usesPreciseCollisionDetection" to true, but it is still problematic. Also, it seems the method is called more times when the bullet hits the player at an angle rather than straight on. Any thoughts how to fix this?

Collision Types:

enum ColliderType:UInt32 {
    case Player = 0b1
    case Bullet = 0b10
}

Player Physics Body Settings:

playerBody!.categoryBitMask = ColliderType.Player.rawValue
playerBody!.contactTestBitMask = ColliderType.Bullet.rawValue
playerBody!.collisionBitMask = ColliderType.Bullet.rawValue

Bullet Physics Body Settings:

bulletBody!.categoryBitMask = ColliderType.Bullet.rawValue
bulletBody!.contactTestBitMask = ColliderType.Player.rawValue
bulletBody!.collisionBitMask = ColliderType.Player.rawValue

Collision Detection Method:

func didBeginContact(contact: SKPhysicsContact) {

    if (contact.bodyA.categoryBitMask == 0b1) && (contact.bodyB.categoryBitMask == 0b10) {
        playerVbullet(contact.bodyA, bullet: contact.bodyB)
    }

    if (contact.bodyA.categoryBitMask == 0b10) && (contact.bodyB.categoryBitMask == 0b11) {
        playerVbullet(contact.bodyB, bullet: contact.bodyA)
    }
}

Function Called on Collision:

func playerVbullet(player:SKPhysicsBody, bullet:SKPhysicsBody) {
    bullet.node?.removeFromParent()
    collisions++
    println(collisions)
}

Solution

  • Give your bullet node a name:

    let bullet = SKSPriteNode()
    bullet.name = "bullet"
    

    Then check your physics contact

    if (contact.bodyA.node?.name == "bullet") {
        contact.bodyA.node?.removeFromParent()
    } else if contact.bodyB.node?.name == "bullet" {
        contact.bodyB.node?.removeFromParent()
    }
    

    Good luck!