出乎意料地发现了Nil SKSpriteNode

时间:2016-04-15 20:02:25

标签: swift sprite-kit skspritenode

当子弹和飞机之间有联系时,我收到以下错误。

  

致命错误:在解包可选值时意外发现nil

Screenshot of error

平面功能:

func addPlane() {
    var myplane : SKSpriteNode?
    myplane = SKSpriteNode(imageNamed: "plane")
    let actualY = random(min: 100, max: size.height - myplane!.size.height/2)
    myplane!.position = CGPoint(x: size.width + myplane!.size.width/2, y: actualY)
    myplane!.physicsBody = SKPhysicsBody(rectangleOfSize: myplane!.size) // 1
    myplane!.physicsBody?.dynamic = false // 2
    myplane!.physicsBody!.categoryBitMask = CollisionCategoryPowerUpOrbs
    myplane!.physicsBody!.collisionBitMask = 0
    myplane!.name = "plan"
    addChild(myplane!)//
    let actualDuration = random(min: CGFloat(2.0), max: CGFloat(4.0))
    let actionMove = SKAction.moveTo(CGPoint(x: -myplane!.size.width/2, y: actualY), duration: NSTimeInterval(actualDuration))
    myplane!.runAction(SKAction.sequence([actionMove]))

}

当用户触摸屏幕时,它将使用此功能拍摄子弹:

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        guard let touch = touches.first else {
            return
        }
        let touchLocation = touch.locationInNode(self)
        var projectile : SKSpriteNode?
        projectile = SKSpriteNode(imageNamed: "bomb")
        projectile!.position = CGPoint(x: 50, y: 100.0)
        projectile!.physicsBody = SKPhysicsBody(circleOfRadius: projectile!.size.width/2)
        projectile!.physicsBody?.dynamic = true
        projectile!.physicsBody!.allowsRotation = false
        projectile!.physicsBody!.categoryBitMask = CollisionCategoryPlayer
        projectile!.physicsBody!.contactTestBitMask = CollisionCategoryPowerUpOrbs
        projectile!.physicsBody!.collisionBitMask = 0
        projectile!.physicsBody!.linearDamping = 1.0
        projectile!.name = "shot"
        let offset = touchLocation - projectile!.position
        if (offset.x < 0) { return }
        addChild(projectile!)
        let direction = offset.normalized()
        let shootAmount = direction * 1000
        let realDest = shootAmount + projectile!.position
        let actionMove = SKAction.moveTo(realDest, duration: 2.0)
        let actionMoveDone = SKAction.removeFromParent()
        projectile!.runAction(SKAction.sequence([actionMove, actionMoveDone]))
}

隐藏联系人平面的功能:

func didBeginContact(contact: SKPhysicsContact) {
    let nodeB = contact.bodyA.node!
    if nodeB.name == "plan" {
        nodeB.removeFromParent()
    }
}

我在addPlane中调用ViewDidLoad函数,如下所示:

runAction(SKAction.repeatActionForever(
    SKAction.sequence([
        SKAction.runBlock(addPlane),
        SKAction.waitForDuration(1.5)
    ])
))

1 个答案:

答案 0 :(得分:1)

使用'?'更改代码做一个零检查:

func didBeginContact(contact: SKPhysicsContact) {

  let nodeB = contact.bodyA.node
  if nodeB?.name == "plan" {     
    nodeB?.removeFromParent()
  }
}

此解决方案可以防止崩溃,但缺点是仍会触发一些不必要的联系事件。

应避免删除didBeginContact中的节点。这可能导致节点已被删除(nil),但PhysicsBody仍处于活动状态。 (另见KnightOfDragon的评论)