纹理中的SKPhysicsBody在Spritekit中发生碰撞时为null



我正在创建一个角色跳跃并收集点(某些对象)的游戏。点击角色时,从图集中执行一些动画。当它接触到这些点时,分数增加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对象具有一个名为node的属性。它是一个可选属性。它表示该实体连接到的节点。在您的情况下,它是蘑菇节点。

因此,当第一次调用didBeginContact时,因为从其父节点中删除了蘑菇节点,所以bodyA.node变为nil。下一次执行bodyA.node!.removeFromParent()将产生崩溃,因为正如我所说,bodyA.node现在为零,但您正在使用强制展开来访问可选项的底层值。

只有当您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()
    }
}

最新更新