Flinigan Flinigan - 1 month ago 13
Swift Question

Not detecting collision

I'm getting some difficulty detecting collision in my SpriteKit Game. I simply want to detect collision between the missiles and the enemies and boats.

I have the ColliderType:

struct ColliderType {
static let Boat: UInt32 = 1
static let Enemy: UInt32 = 2
static let Wall: UInt32 = 3
static let Bullet: UInt32 = 4

}

class GameplayScene: SKScene, SKPhysicsContactDelegate {

var player = SKSpriteNode()
var enemy = SKSpriteNode()
var boat = SKSpriteNode()
var missile = SKSpriteNode()


The didBegin contact:

func didBegin(_ contact: SKPhysicsContact) {

var firstBody = SKPhysicsBody()
var secondBody = SKPhysicsBody()

if contact.bodyA.node?.name == "Missile" {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}

if firstBody.node?.name == "Missile" && secondBody.node?.name ==
"Enemy" {
incrementScore()
secondBody.node?.removeFromParent()
} else if firstBody.node?.name == "Missile" &&
secondBody.node?.name == "Boat" {
incrementScore()
}

}



  • I have added the "physicsWorld.contactDelegate = self" in the didMove toview



I have also added physicsBodies to all the relevant spritenodes:

func fireMissile() {
let missile = SKSpriteNode(color: .yellow, size: CGSize(width: 20,
height: 5))
missile.name = "Missile"
missile.position = CGPoint(x: player.position.x + 28, y:
player.position.y + 10)
missile.zPosition = 2
missile.physicsBody = SKPhysicsBody(rectangleOf: missile.size)
missile.physicsBody?.isDynamic = false
missile.physicsBody?.categoryBitMask = ColliderType.Bullet
missile.physicsBody?.collisionBitMask = ColliderType.Enemy |
ColliderType.Boat
missile.physicsBody?.contactTestBitMask = ColliderType.Enemy |
ColliderType.Boat


self.addChild(missile)

}


func createEnemies() {
let enemy = SKSpriteNode(imageNamed: "Enemy1")
enemy.name = "Enemy"
enemy.anchorPoint = CGPoint(x: 0.5, y: 0.5)
enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.size.height
/ 2)
enemy.physicsBody?.categoryBitMask = ColliderType.Enemy
enemy.physicsBody?.affectedByGravity = false
enemy.physicsBody?.isDynamic = false
enemy.zPosition = 3

enemy.position.y = self.frame.height + 100
enemy.position.x = CGFloat.randomBetweenNumbers(firstNum: -347.5,
secondNum: -85)


self.addChild(enemy)

}


func createBoat() {
let boat = SKSpriteNode(imageNamed: "Boat")
boat.name = "Boat"
boat.anchorPoint = CGPoint(x: 0.5, y: 0.5)
boat.physicsBody = SKPhysicsBody(circleOfRadius: boat.size.height /
2)
boat.physicsBody?.categoryBitMask = ColliderType.Boat
boat.physicsBody?.affectedByGravity = false
boat.physicsBody?.isDynamic = false
boat.zPosition = 3

boat.position.y = self.frame.height + 100
boat.position.x = CGFloat.randomBetweenNumbers(firstNum: 0,
secondNum: 0)


self.addChild(boat)


}

Answer Source

Firstly, some of your categories are wrong:

static let Wall: UInt32 = 3
static let Bullet: UInt32 = 4

This effectively defines Wall as being both a Boat and an Enemy. Change them to:

static let Wall: UInt32 = 4
static let Bullet: UInt32 = 8

(Categories should always be unique powers of 2 - 1, 2, 4, 8, 16 etc).

The rest looks ok, so try that and let us know if it’s working.

Edit:

OK - just noticed that all of your physics bodies have their isDynamic property set to false - this means that, among other things, the body will not trigger contacts. so if you want missile to generate contacts with either enemy or boat, then either missile should be dynamic or both enemy and boat should be dynamic (only 1 of the 2 objects involved in a contact needs to by dynamic).