Search code examples
iossprite-kitskphysicsbodysknodeskphysicscontact

SpriteKit crash: how can physics body lose association with SKNode?


This code crashes because secondBody is not associated with a node.

func didBegin(_ contact: SKPhysicsContact) {
    // Set vars to hold bodies
    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody

    // Sort bodies
    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    // Handle different contacts
    if firstBody.categoryBitMask == BallBitMask && secondBody.categoryBitMask == TileBitMask {
        didBallTileHit(tile: secondBody.node!) // Code crashes here :(
    }

    ...
}

1) Aside from setting a physics body to nil, what would cause a physics body to lose association with a node in SpriteKit?

2) How can a physics body even exist without a node in the first place?


Solution

  • An SKSPhysicsBody is an object in itself and perfectly capable of being created yet not associated with an SKSpriteNode (although perhaps not of much use :-) )

    In your didBallTileHit(), do you removeFromParent() any of the nodes? If so, this is probably the cause of your crash in that Sprite-Kit has generated multiple collisions between 2 objects and is calling didBegin() several times for the 2 nodes. If you then go and remove one of the nodes in the 1st call to didBegin(), it won't be there for the 2nd and subsequent calls.

    The way to handle it (you can't get sprite-kit to NOT call didBegin multiple times in some circumstances) is to make sure that your contact code accommodates this and that handling the contract multiple times does not cause a problem (such as adding to the score multiple times, removing multiple lives, trying to access a node or physicsBody that has been removed etc).

    For more detail and possible solutions, see this answer : https://stackoverflow.com/a/44384390/1430420