Reputation: 432
I have a SpriteKit game where you must shoot down asteroids before they hit the base. But if you shoot and hit the asteroid and/or the base when the asteroid is hitting the base, the program crashes.
Here's my physics contact code.
public func didBegin(_ contact: SKPhysicsContact) {
//Asteroid is object 1, other item is object 2
var object1 = SKSpriteNode()
var object2 = SKSpriteNode()
//Test for asteroid/projectile contact, then remove appropriate sprites, change game values and play sounds
if contact.bodyA.contactTestBitMask == ColliderType.Asteroid.rawValue && contact.bodyB.contactTestBitMask == ColliderType.Asteroid.rawValue{
if contact.bodyA.categoryBitMask == ColliderType.Asteroid.rawValue{
}else if contact.bodyB.categoryBitMask == ColliderType.Asteroid.rawValue{
object2 = contact.bodyA.node as! SKSpriteNode
object1 = contact.bodyB.node as! SKSpriteNode
let explosionPath = URL(fileURLWithPath: Bundle.main.path(forResource: "astd", ofType: "m4a")!)
do {
audioPlayer = try AVAudioPlayer(contentsOf: explosionPath)
} catch {
print("error")
}
audioPlayer.prepareToPlay()
audioPlayer.play()
}
if object2.physicsBody?.categoryBitMask == ColliderType.Object.rawValue{
object1.removeAllActions()
object1.removeFromParent()
let hitPath = URL(fileURLWithPath: Bundle.main.path(forResource: "craftHit", ofType: "mp3")!)
do {
audioPlayer = try AVAudioPlayer(contentsOf: hitPath)
} catch {
print("error")
}
audioPlayer.prepareToPlay()
audioPlayer.play()
reduceHealthBy(num: 0.075)
}else if object2.physicsBody?.categoryBitMask == ColliderType.Projectile.rawValue{
object1.removeAllActions()
object1.removeFromParent()
object2.removeAllActions()
object2.removeFromParent()
score += 1
}
}
}
Upvotes: 3
Views: 104
Reputation: 8134
Sounds like a duplicate of Optional unwrapping SKPhysics error
SK is generating multiple contact events for one actual contact and so didBegin()
is being called multiple times.
On the first call to didBegin you handle the contact and remove one or mode nodes etc, and on the second call to didBegin (with the same contact: argument) the nodes you removed are now nil, so when you try to remove or reference them you get a crash.
There are several ways to handle this such as adding the nodes to be removed to a set and then removing them in didFinishUpdate()
or checking if a node is nil and then returning if it is etc.
Trying to get SK to NOT generate the multiple contacts currently seems unachievable.
Upvotes: 2