这是“didBeginContact”方法中的代码:
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask
{
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000003"{
contact.bodyB.node!.removeFromParent()
}
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{
contact.bodyB.node!.removeFromParent()
}
}
else
{
if contact.bodyB.node!.name == "0" && contact.bodyA.node!.name == "1000003"{
contact.bodyA.node!.removeFromParent()
}
if contact.bodyB.node!.name == "0" && contact.bodyA.node!.name == "1000004"{
contact.bodyA.node!.removeFromParent()
}
}
它在“iPhone 4s”和“iPhone 5”模拟中工作,并在更高版本中失败并显示此错误消息:
“ fatal error :在展开可选值时意外发现 nil (lldb)”
这是标记为红色的行:
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{
很高兴知道:
名称为“1000004”的对象是我在“GameScene”类中创建的 SKSpriteNode:let TestPixel = SKSpriteNode(imageNamed: "6")
此对象的属性位于“touchesBegan”方法中。 这是代码:
TestPixel.name = "1000004"
TestPixel.anchorPoint = CGPointMake(0.5, 0.5)
TestPixel.userInteractionEnabled = false
TestPixel.zPosition = 1000003
TestPixel.size = CGSizeMake(1, 1)
TestPixel.position = CGPointMake(positionInScene.x, positionInScene.y)
TestPixel.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "6"), size: TestPixel.size)
TestPixel.physicsBody?.categoryBitMask = ClickOnCategory
TestPixel.physicsBody?.contactTestBitMask = BuildingsCategory
TestPixel.physicsBody?.affectedByGravity = false
TestPixel.physicsBody?.dynamic = true
TestPixel.physicsBody?.collisionBitMask = 0
addChild(TestPixel)
如果此 SpriteNode(name:"1000004") 命中我在“didMoveToView”方法中创建的另一个 SpriteNode,则会发生错误,代码如下:
func addBG(){
let background = SKSpriteNode(imageNamed: "0")
background.name = "0"
background.anchorPoint = CGPointMake(0.5, 0.5)
background.zPosition = 1
background.position = CGPointMake(CGRectGetMinX(self.frame)+self.frame.width/4,CGRectGetMaxY(self.frame)-self.frame.height/4)
background.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "0"), size: background.size)
background.physicsBody?.categoryBitMask = BuildingsCategory
background.physicsBody?.affectedByGravity = false
background.physicsBody?.dynamic = true
background.physicsBody?.collisionBitMask = 0
self.addChild(background)
}
addBG()
在“didMoveToView”中也是:
physicsWorld.contactDelegate = self
“GameScene”类中的categoryBitMask是这样设置的:
class GameScene: SKScene, SKPhysicsContactDelegate{
let BuildingsCategory : UInt32 = 0x1 << 1
let ClickOnCategory : UInt32 = 0x1 << 2
是的,正如我所说,它可以在“iPhone 4s”&&“iPhone 5”的模拟器中运行,但不能在更高版本中运行……有什么想法吗? 谢谢
最佳答案
是的,我可以告诉你原因:
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000003"{
contact.bodyB.node!.removeFromParent() <----PROBLEM
}
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{
contact.bodyB.node!.removeFromParent()
}
发生了什么事,你正在点击你的第一个 if 语句,它从父级中删除,然后你试图再次访问它。好吧,如果你从父节点中删除,是什么在内存中维护节点?可能什么都没有,所以在第一行,它消除了节点。然后你的代码继续进入另一个 if 条件,你现在正试图打开一个 nil。这是您将使用 ELSE IF
而不是 if 的地方。
我强烈建议使用 sprite kit 做的另一件事是永远不要在接触阶段移除节点。您可能会发生多个联系,并且您可能需要处理所有这些联系情况,因此最好让节点保持事件状态。
相反,每当您想要删除节点时,将它们放入队列(数组或集合),然后在您的 didFinishUpdate 方法中循环遍历队列并删除所有节点。
我做的另一个技巧是,我在 categoryBitMask 上保留第 31 位以确定 Sprite 是活的还是死的,然后在 didContact 方法上,我对其进行了防范。
例如
func didBeginContact(contact: SKPhysicsContact!)
{
guard let bodies = (a:contact.bodyA,b:contact.bodyB) where a.categoryBitMask < 1 << 31 && b.categoryBitMask < 1 << 31
else
{
return
}
// do other work here
}
赛夫特 3.0
func didBeginContact(contact: SKPhysicsContact!)
{
guard let bodies = (a:contact.bodyA,b:contact.bodyB, a.categoryBitMask < 1 << 31 && b.categoryBitMask < 1 << 31
else
{
return
}
// do other work here
}
关于如果在模拟器中运行较新的 iPhone,didBeginContact 中会出现快速错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39082179/