Texture 中的 SKPhysicsBody 在 Spritekit 中碰撞时给出空值

SKPhysicsBody from Texture gives null on collision in Spritekit

我正在创建一个角色跳跃和收集点数的游戏(一些 OBJECT)。当您点击角色时,从图集执行一些动画。当它触及点时,分数增加 1。我正在使用 SKTexture 来创建角色的物理身体。当我的角色触及它崩溃的点并向我显示此错误

fatal error: unexpectedly found nil while unwrapping an Optional value 

//代码

 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))

但是,如果我从矩形或圆形创建 Physicsbody,它就可以正常工作。也许这与我用来制作角色动画的地图集有关。

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

当角色接触到蘑菇时它会崩溃。 工作演示: https://github.com/nak1b/demo-game-error

您的代码的问题是 didBeginContact 被多次调用...您可以通过在 if 块中放置一个 print() 语句来检查这一点。

如您所知,SKPhysicsBody object 有一个 属性 称为 node。它是一个可选的 属性。它表示此 body 连接到的节点。在您的情况下,这是一个蘑菇节点。

所以当didBeginContact第一次被调用时,因为你从它的parent中移除了一个蘑菇节点,bodyA.node变成了nil。下次执行 bodyA.node!.removeFromParent() 将产生崩溃,因为正如我所说,bodyA.node 现在为 nil 但您正在使用强制解包来访问可选的基础值。

仅当您 100% 确定基础值不为零时(或者如果您有意在开发阶段触发错误),才使用强制解包。否则使用可选绑定或可选链接。像这样:

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()
    }
}