SpriteKit崩溃:物理体如何与SKNode失去联系?

时间:2017-08-29 00:49:08

标签: ios sprite-kit skphysicsbody sknode skphysicscontact

此代码崩溃,因为secondBody未与节点关联。

func didBegin(_ contact: SKPhysicsContact) {
    // Set vars to hold bodies
    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody

    // Sort bodies
    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
        firstBody = contact.bodyA
        secondBody = contact.bodyB
    } else {
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    }

    // Handle different contacts
    if firstBody.categoryBitMask == BallBitMask && secondBody.categoryBitMask == TileBitMask {
        didBallTileHit(tile: secondBody.node!) // Code crashes here :(
    }

    ...
}

1)除了将物理主体设置为nil之外,还有什么会导致物理主体失去与SpriteKit中节点的关联?

2)物理体如何在没有节点的情况下甚至存在?

2 个答案:

答案 0 :(得分:1)

SKSPhysicsBody本身就是一个对象,完全有能力创建但与SKSpriteNode无关(尽管可能没什么用处:-))

didBallTileHit()中,您removeFromParent()是否有任何节点?如果是这样,这可能是导致崩溃的原因,因为Sprite-Kit在2个对象之间产生了多次冲突,并且为2个节点多次调用didBegin()。然后,如果您继续将第一个呼叫中的一个节点移至didBegin(),则第二次和后续呼叫将不会出现这种情况。

处理它的方法(你不能让sprite-kit在某些情况下多次调用didBegin)是为了确保你的联系代码适应这一点,多次处理合同不会导致问题(例如多次添加分数,删除多个生命,尝试访问已被删除的节点或物理等。)

有关更多详细信息和可能的解决方案,请参阅以下答案:https://stackoverflow.com/a/44384390/1430420

答案 1 :(得分:1)

您可以使用不同的方法处理联系。

更简单的方法是:

func didBegin(_ contact: SKPhysicsContact) {

    let bodyA = contact.bodyA
    let bodyB = contact.bodyB

    guard let nodeA = bodyA.node as? SKSpriteNode,
          let nodeB = bodyB.node as? SKSpriteNode,
          let parentNodeA = nodeA.parent,
          let parentNodeB = nodeB.parent
    else {return}

    //all your stuff
}