Reputation: 21
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
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:
If you have 3 bodies (a
, b
, c
) that collide, and collision logic applies to all 3, sprite kit will perform 2 collision checks:
a
and b
b
and c
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
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
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
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