ymulki
ymulki

Reputation: 432

SpriteKit game crashes when two SKPhysicsContacts are detected

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

Answers (1)

Steve Ives
Steve Ives

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

Related Questions