2017-03-17 45 views
1

在我被钉死在downvotes之前让我说我已经做了这个研究,我仍然不明白为什么我得到这个错误。可选解开SKPhysics错误

我有一个核心,玩家试图捍卫,你可以从它射出小激光来抵御流入的流星。那么,我已经设置好了一切(大部分时间都是这样),但是每当激光撞击流星时,我的碰撞处理函数都会尝试去除镜头节点和流星节点,它会引发此错误:

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中删除节点时才抛出,我尝试了许多不同的方法来解决此问题,但无法为我的生活弄清楚。任何帮助表示感谢,谢谢!

回答

2

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

第一次被称为,一切都很好;第二次,事情已被删除,一些节点和/或机构是零。

检查这个答案,看看是否有帮助: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") 
     } 
    } 

这是真的只有安全的,如果您的节点只属于一次一个范畴,它是由你来决定。

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

+1

我很怀疑!当我试图调试这个时,我得到了多次调用didBegin,但我不知道如何解决它。非常感谢您,我一定会检查您链接的答案。另外感谢清理我的collisionBetween函数,这是相当混乱,你的方法清理了一堆。非常感谢! –