SKPhysicsBody from Texture gives null on collision in Spritekit

别来无恙 提交于 2019-12-24 07:39:35

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!