问题
I am creating a game where character jumps and collect points (SOME OBJECT). When you tap character perform some animation from atlas. When it touches the points, score is increased by 1. I am using SKTexture to create physicbody of the character. When my character touches the point it crashes and show me this error
fatal error: unexpectedly found nil while unwrapping an Optional value
//Code
Cat = SKSpriteNode(imageNamed: "cat");
Cat.size = CGSize(width: 100, height: 100)
Cat.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
//physics
Cat.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "cat"), size:CGSizeMake(100, 100))
But if i create Physicsbody from rectangle or circle it works just fine. Maybe its to do with atlases i am using to animate my character.
Cat.physicsBody = SKPhysicsBody(circleOfRadius: self.frame.width/2)
When the character touches the mushroom it crashes. Working Demo: https://github.com/nak1b/demo-game-error
回答1:
The problem with your code is that didBeginContact
is being called multiple times... You can check this by putting a print()
statement inside of that if
block.
As you already know, an SKPhysicsBody
object has a property called node
. It is an optional property. It represents the node that this body is connected to. In your case that is a mushroom node.
So when didBeginContact
is called for the first time, because you remove a mushroom node from its parent, bodyA.node
becomes nil
. Next time doing bodyA.node!.removeFromParent()
will produce a crash, because, as I said, bodyA.node
is now nil but you are using forced unwrapping to access underlying value of an optional.
Use forced unwrapping only when you are 100% positive that underlying value is not nil (or if you intentionally want to trigger an error during the development phase). Otherwise use optional binding or optional chaining. Like this:
func didBeginContact(contact: SKPhysicsContact) {
var firstBody, secondBody: SKPhysicsBody
//Do this to avoid double checking
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
//No need for double-checking now
if ((firstBody.categoryBitMask & PhysicsCategory.Panda) != 0 &&
(secondBody.categoryBitMask & PhysicsCategory.Score != 0)) {
//This will fail gracefully if node property is nil
secondBody.node?.removeFromParent()
}
}
来源:https://stackoverflow.com/questions/36970700/skphysicsbody-from-texture-gives-null-on-collision-in-spritekit