可选展开SKPhysics错误

时间:2017-03-17 03:29:03

标签: swift sprite-kit collision-detection physics optional

在我被钉死之前让我说我已经对此做了研究,我仍然无法理解为什么我会收到这个错误。

我有一个核心,玩家正试图防守,你可以用它射出一些小激光来防御来袭的流星。好吧,我已经设置好了所有的工作(大部分时间都是这样),但每当激光击中流星并且我的碰撞处理函数试图移除射击节点和流星节点时,它会抛出此错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

我再次对此进行了大量挖掘,似乎无法弄明白。

这是我的didBegin:

func didBegin(_ contact: SKPhysicsContact) {
    if (contact.bodyA.node?.name == "shot") { // shot A
        collisionBetween(first: (contact.bodyA.node)!, second: (contact.bodyB.node)!)
    } else if (contact.bodyB.node?.name == "shot") { // shot B
        collisionBetween(first: (contact.bodyB.node)!, second: (contact.bodyA.node)!)
    }
    if (contact.bodyA.node?.name == "core") { // core A
        collisionBetween(first: (contact.bodyA.node)!, second: (contact.bodyB.node)!)
    } else if (contact.bodyB.node?.name == "core") { // core B
        collisionBetween(first: (contact.bodyB.node)!, second: (contact.bodyB.node)!)
    }

}

这是我的collisionBetween函数:

func collisionBetween(first: SKNode, second: SKNode) {

    if first.name == "shot" && second.name == "sMeteor" {
        first.removeFromParent()    // these two only throw the error
        second.removeFromParent()   // every once and a while
    } else if first.name == "sMeteor" && second.name == "shot" {
        first.removeFromParent()    // these two throw the error also
        second.removeFromParent()   // but only on occasion
    } else if first.name == "mMeteor" && second.name == "shot" {
        second.removeFromParent()
    } else if first.name == "shot" && second.name == "mMeteor" {
        first.removeFromParent()
    }
    if first.name == "core" && second.name == "sMeteor" {
        second.removeFromParent() //always throws the error
    } else if first.name == "sMeteor" && second.name == "core" {
        first.removeFromParent() //always throws the error
    }

}

我一直试图将这个错误弄清楚一段时间,我觉得我对选项有了基本的了解。当我尝试从父self中删除节点时,只会抛出这些错误,并且我已经尝试了许多不同的方法来解决这个问题,但是在我的生活中无法解决这个问题。感谢任何帮助,谢谢!

1 个答案:

答案 0 :(得分:2)

我强烈怀疑这是由SpriteKit为同一个联系人生成多个联系事件引起的。 (即它使用相同的身体A&amp ;;它呼叫didBegin())2次或更多次bodyB)

第一次被叫,一切都很好;第二次,事情已被删除,一些节点和/或身体是零。

检查此答案,看看是否有帮助:Sprite-Kit registering multiple collisions for single contact

如果您在didBegin()中添加了一些打印陈述,例如

func didBegin(_ contact: SKPhysicsContact) {
    print("Contact between \(contact.bodyA.node?.name) & \(contact.bodyB.node?.name)")
    if (contact.bodyA.node?.name == "shot") { // shot A

你可能已经在日志中看到了:

Contact between shot and sMeteor
Contact between shot and sMeteor
Contact between shot and sMeteor

仅发生1次接触时。

此外,您的didBegin()collisionBetween()函数看起来过于复杂(加上collisionBetween应该真正称为contactBetween())。

我发现代码didBegin()的一种更简洁的方法是:

 func didBegin(contact: SKPhysicsContact) {
            let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

            switch contactMask {

            case categoryBitMask.shot | categoryBitMask.sMeteor:
               print("Collision between shot and sMeteor")
               contact.bodyA.removeFromParent()
               contact.bodyB.removeFromParent()

            case categoryBitMask.shot | categoryBitMask.mMeteor:
               print("Collision between shot and mMeteor")
               let shot = contact.bodyA.categoryBitMask == categoryBitMask.shot ? contact.bodyA.node! : contact.bodyB.node!
               shot.removeFromParent()

            case categoryBitMask.core | categoryBitMask.sMeteor:
               print("Collision between core and sMeteor")
               let meteor = contact.bodyA.categoryBitMask == categoryBitMask.sMeteor ? contact.bodyA.node! : contact.bodyB.node!
               meteor.removeFromParent()

            default :
               //Some other contact has occurred
               print("Some other contact")
        }  
    }

如果您的节点一次只属于一个类别,这实际上是安全的,由您决定。

如果'核心'会发生什么?和' mMeteor'联系?