Texture's SKPhysicsBody gives null on collision in Spritekit

I create a game where the character jumps and collects points (SOME OBJECT). When you click a symbol, perform an animation from the atlas. When it touches points, the score increases by 1. I use SKTexture to create the character’s physical body. When my character touches a point, it falls and shows 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 a Physicalbody from a rectangle or circle, it works fine. Perhaps this is due to the atlases that I use to animate my character.

 Cat.physicsBody = SKPhysicsBody(circleOfRadius: self.frame.width/2) 

When a character touches a mushroom, it falls. Working demo: https://github.com/nak1b/demo-game-error

+1
source share
1 answer

The problem with your code is that didBeginContact is called several times ... You can verify this by placing the print() if inside this if block.

As you already know, the SKPhysicsBody object has a node property. This is an optional property. It represents the node this body is associated with. In your case, it is a node mushroom.

So, when didBeginContact is called for the first time because you remove the node mushroom from your parent, bodyA.node becomes nil . The next time doing bodyA.node!.removeFromParent() will crash, because, as I said, bodyA.node now zero, but you use forced deployments to access the base cost optional.

Use forced deployment only when you are 100% sure that the base value is not zero (or if you intentionally want to cause an error at the design stage). Otherwise, use extra binding or extra chain. 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() } } 
+2
source

Source: https://habr.com/ru/post/1260078/


All Articles