可选的解包SKPhysics错误 [英] Optional unwrapping SKPhysics error
问题描述
在我被选票钉死之前,我先说我已经对此进行了研究,但我仍然不明白为什么会收到这个错误.
Before I'm crucified with downvotes let me say I have done research into this and I still cannot understand why I am getting this error.
我有一个核心,玩家正在努力防御,您可以从中射出一点激光来防御来袭的流星.好吧,我已经完成了所有工作并正常工作(无论如何大部分时间都是如此),但是每隔一段时间,当激光束撞击流星并且我的碰撞处理功能试图删除发射节点和流星节点时,就会引发此错误:>
I have a core that the player is trying to defend and you can shoot little lasers out from it to defend against incoming meteors. Well, I have everything set up and working (most of the time anyways), but every once and while when a laser hits a meteor and my collision handling function tries to remove the shot node and meteor node, it throws this error:
fatal error: unexpectedly found nil while unwrapping an Optional value
同样,我已经做了很多深入的研究,但我似乎无法弄清楚.
Again I have done a lot of digging into this and I cannot seem to figure it out.
这是我的didBegin:
Here's my 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函数:
and here's my collisionBetween function:
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
中删除节点时才抛出这些错误,并且我尝试了许多不同的方法来解决此问题,但我一生都无法解决.任何帮助表示感谢,谢谢!
I've been trying to figure this error out for a while now, and I feel like I have a basic understanding of optionals. These errors are only thrown when I try to remove the nodes from the parent self
and I have tried many different approaches to solving this problem but cannot for the life of me figure it out. Any help appreciated, thanks!
推荐答案
我强烈怀疑这是由SpriteKit为同一联系人生成多个联系人事件引起的. (也就是呼叫didBegin()
)2次或更多次,且主体相同bodyB)
I strongly suspect that this is caused by SpriteKit generating multiple contact events for the same contact. (i.e. it's calling didBegin()
) 2 or more times with the same bodyA & bodyB)
第一次调用它,一切都很好;第二次,已将其删除,并且某些节点和/或实体为零.
The first time it is called, everything is fine; the second time, things have been removed and some nodes and/or bodies are nil.
检查此答案以查看是否有帮助: Sprite-Kit为单个联系人注册多个碰撞
Check this answer to see if it helps : Sprite-Kit registering multiple collisions for single contact
如果要在didBegin()
中放入一些打印语句,例如
If you'd put some print statements in your didBegin()
e.g.
func didBegin(_ contact: SKPhysicsContact) {
print("Contact between \(contact.bodyA.node?.name) & \(contact.bodyB.node?.name)")
if (contact.bodyA.node?.name == "shot") { // shot A
您可能已经在日志中看到了
you'd probably have seen in the log:
Contact between shot and sMeteor
Contact between shot and sMeteor
Contact between shot and sMeteor
只有1个联系人发生时.
when only 1 contact has occurred.
此外,您的didBegin()
和collisionBetween()
函数看起来过于复杂(加上collisionBetween
应该真正称为contactBetween()
).
Also, your didBegin()
and collisionBetween()
functions look overly complicated (plus collisionBetween
should really be called contactBetween()
).
我发现编码didBegin()
的更整洁的方式是:
I find a neater way to code didBegin()
is :
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")
}
}
只有在您的节点一次仅属于一个类别(这完全由您决定)的情况下,这才真正安全.
This is really only safe if your nodes only belong to one category at a time, which is up to you to determine.
如果核心"和"mMeteor"建立联系会发生什么?
What happens if 'core' and 'mMeteor' make contact?
这篇关于可选的解包SKPhysics错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!