节点联系时收到错误

时间:2017-07-04 01:33:27

标签: swift xcode sprite-kit

我正在制作一个游戏,你在中间是一艘太空飞船,有敌舰向你移动,你必须向他们射击才能获胜。

当我在测试游戏时,我看到当两艘或更多敌舰同时击中玩家船时,我收到了一个错误。我不确定这是否是导致错误的原因,但是当我测试它时它看起来就好了。

我制作游戏,以便每当敌方玩家触摸玩家时,游戏结束并调用一个函数来改变游戏场景。无论何时场景即将发生变化,都会调用此错误。

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

这里是didBegin的代码(联系方式:SKPhysicsContact)

func didBegin(_ contact: SKPhysicsContact) {

    var BodyOne = SKPhysicsBody()
    var BodyTwo = SKPhysicsBody()


    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask{
        BodyOne = contact.bodyA
        BodyTwo = contact.bodyB
                }
    else{
        BodyOne = contact.bodyB
        BodyTwo = contact.bodyA
    }


    //SHIPS TOUCH EACH OTHER CHECK
    if BodyOne.categoryBitMask == NumberingPhysics.SpaceShip && BodyTwo.categoryBitMask == NumberingPhysics.LeftV{



        GameOver1()

       BodyTwo.node?.removeFromParent()
       BodyOne.node?.removeFromParent()

    }

    if BodyOne.categoryBitMask == NumberingPhysics.SpaceShip && BodyTwo.categoryBitMask == NumberingPhysics.RightV{

        GameOver1()
        BodyOne.node?.removeFromParent()
        BodyTwo.node?.removeFromParent()


        //more code is under here 

    }

这是游戏改变场景的代码。 (当1个敌人触及玩家但在2个或更多玩家与玩家接触时似乎不起作用)

func GameOver1(){

    ButtonAudioPlayer.stop()
    removeAllChildren()
    removeAllActions()
    let scene = GameOver(size: self.size)
    let sKView = self.view! as SKView       // <----- error shows here
    sKView.ignoresSiblingOrder = true
    scene.scaleMode = .aspectFill
    sKView.presentScene(scene)


}

有人可以帮我解决这个问题。

1 个答案:

答案 0 :(得分:2)

您的视图对象为nil,如果您在活动场景中定义GameOver1,这是很奇怪的。将GameOver1功能移动到主场景,这应解决问题。

或者,您可以创建一个全局变量并将其分配给GameViewController内的初始SKView对象。这不是最佳做法,但可行。

var gView = SKView()

class GameViewController: UIViewController {
  // Stuff..

  if let view = self.view as! SKView? {
      gView = view

此外,此代码中还有其他潜在的崩溃问题。

正如KOD在评论中所说的那样,多个联系人可以在1帧中发生..但是你正在杀死节点(因此pb),这意味着预定的.didBegin将会找到nil或其他一些错误和崩溃。

更好的方法是在物理步骤之后标记要删除的节点 - 一旦安全处理联系人。

将他们的面具设置为某个高数字,而不是删除它:

var nodesToKill = SKNode()

override func didBeginContact(/*prams*/) {
  // Stuff...

  BodyB.node!.categoryBitMask = 35 // Or some other number so as 
                                   // to not trigger another contact.
  BodyB.node!.moveToParent(nodesToKill) //moves the node off the scene entirely
}

override func didSimulatePhysics(/*prams*/) { 

  nodesToKill.removeAllChildren() // or do nodesToKill = SKNode() and let ARC take care of it for you
}

此外,您可能希望在调用GameOver之前删除所有节点,因为这会导致尝试使用不再存在的节点时出现问题。

一种有点人为的方法(如果以上没有工作)是这样的:

var flag_shouldGameOver = false

override func didFinishUpdate() {
  if flag_shouldGameOver == true {
     flag_shouldGameOver = false
     GameOver1()
  }
}