节点接触时收到错误 [英] Receiving an error when nodes make contact

查看:25
本文介绍了节点接触时收到错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在制作一个游戏,其中你是一艘太空船,有敌舰向你移动,你必须向它们射击才能获胜.

I am currently making a game in which you are a space ship in the middle and there are enemy ships moving towards you and you have to shoot at them to win.

在测试游戏时,我发现当(似乎是)两艘或更多敌舰同时击中玩家舰船时,我收到了错误消息.我不确定这是否是导致错误的原因,但在我测试时看起来是这样.

While I was testing the game I saw that I received an error when (it appears to be) two or more enemy ships hit the player ship at the same time. I am not certain if this is what's causing the error but it looks like it when I test it.

我制作了这个游戏,每当敌方玩家接触玩家时,游戏就会结束并调用一个函数来改变游戏场景.每当场景即将发生变化时,就会在此处调用错误.

I made the game so that whenever enemy players touch the player, the game ends and a function is called to change the game scene. This is where the error is called, whenever the scene is about to change.

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

"fatal error: unexpectedly found nil while unwrapping an Optional value"

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

here is the code for the didBegin(contact: 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 个或更多敌人与玩家接触时似乎不起作用)

And here is the code of the game changing scene. (which works when 1 enemy touches the player but doesn't seem to when 2 or more makes contact with the player)

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)


}

谁能帮我解决这个问题.

Can someone please help me resolve this issue.

推荐答案

你的视图对象是 nil,如果你在活动场景中定义 GameOver1,这是很奇怪的.将您的 GameOver1 函数移动到您的主场景,这应该可以解决问题.

Your view object is nil, which is peculiar if you are defining GameOver1 inside of the active scene. Move your GameOver1 function to your main scene, and that should fix the issue.

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

Or, you could make a global variable and assign it to the initial SKView object inside of your GameViewController. This is not a best practice but it will work.

var gView = SKView()

class GameViewController: UIViewController {
  // Stuff..

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

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

Also, you have other potential crash issues in this code.

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

As KOD said in comments multiple contacts can happen in 1 frame.. but you are killing the node (and thus pb) which means the scheduled .didBegin is going to find nil or some other error and crash.

一个更好的方法是在物理步骤之后标记要移除的节点——一旦接触被安全处理.

A better way to do this is to flag the node for removal AFTER the physics step--once contacts are safely handled.

将他们的掩码设置为一些高数字而不是删除它:

Set their mask to some high-number instead of removing it:

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 之前删除所有节点,因为这也会导致尝试对不再存在的节点执行操作时出现问题.

Also, you probably want to all of the node removal stuff BEFORE calling GameOver, as that can cause issues as well with trying to do stuff with nodes that no longer exist.

一个有点人为的方法(如果上述方法不起作用)是这样的:

A somewhat contrived way around this (if the above didn't work) is something like this:

var flag_shouldGameOver = false

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

这篇关于节点接触时收到错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆