Pretorian
Pretorian

Reputation: 21

Hit fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)

I programming a simple game and at the first collision I get the following error:

Hit fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)

Here's my code:

func didBeginContact(contact: SKPhysicsContact) {

    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB

    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
        (secondBody.categoryBitMask & PhysicsCategory.naboj != 0)) {
            projectileDidCollideWithMonster(firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode)

    }

}

Upvotes: 0

Views: 778

Answers (4)

Abdul Ahmad
Abdul Ahmad

Reputation: 10021

I had the same problem before, this is what I did

Basically, when you're unwrapping the physics body (this usually happens at the line that says secondBody.node!) the following happens:

  1. If you have 3 bodies (a, b, c) that collide, and collision logic applies to all 3, sprite kit will perform 2 collision checks:

    • One with bodies a and b
    • then with bodies b and c
  2. you are removing bodies on collision:

    • first detection : bodies a and b are unwrapped, bodies a and b are removed

    • second detection : only body c is left because a and b were removed. This means secondBody or firstBody is now nil. So the error is thrown

Try changing your code to the following, and it should fix the issue:

var firstBody: SKPhysicsBody?
var secondBody: SKPhysicsBody?

if (firstBody!.node! != nil && secondBody!.node! != nil) {
       if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
                (secondBody.categoryBitMask & PhysicsCategory.Projectile != 0)) {
                projectileDidCollideWithMonster(secondBody.node!, monster: firstBody.node!)
        }
}

Upvotes: 6

Nusonic
Nusonic

Reputation: 17

Ok this took me a while to figure out but I got it in the end. I tried most of the other solutions I could find online with very little luck. I had to figure it out the hard way. What you have to do is give the option of a break/ return if a nil is found. Because most of the time this error occurs when two of the same collisions are triggered simultaneously.

what I did is make a if else statement to return the function if a nil occurs.

func didBeginContact(contact: SKPhysicsContact) {

var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody

if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
    firstBody = contact.bodyA
    secondBody = contact.bodyB

} else {
    firstBody = contact.bodyB
    secondBody = contact.bodyA
}

if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
    (secondBody.categoryBitMask & PhysicsCategory.naboj != 0)) {
// new part
    if (firstBody.node == nil || secondBody.node == nil)
    {return}

else {
 projectileDidCollideWithMonster(firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode)
}}}

I hope this helps. It is also important that you treat it like you are expecting a nil by having the return statement in the if and not the else.

Upvotes: 0

T. Vel
T. Vel

Reputation: 1

Try this way:

if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
    (secondBody.categoryBitMask & PhysicsCategory.naboj != 0)) {
    if(firstBody.node != nil && secondBody.node != nil ) {
        projectileDidCollideWithMonster(firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode) }
}

Upvotes: 0

Sunkas
Sunkas

Reputation: 9590

Are you using swift 1 or 1.2?

Try

if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
    (secondBody.categoryBitMask & PhysicsCategory.naboj != 0)) {

    if let firstNode = firstBody.node as? SKSprintNode,
       let secondNode = secondBody.node as? SKSprinteNode {

       projectileDidCollideWithMonster(firstNode, monster: secondNode)
    }
}

Upvotes: 3

Related Questions