【问题标题】:SpriteKit crash: how can physics body lose association with SKNode?SpriteKit 崩溃:物理体如何与 SKNode 失去关联?
【发布时间】:2017-08-29 00:49:08
【问题描述】:

此代码崩溃,因为 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) 一开始就没有节点,物理体怎么可能存在?

【问题讨论】:

  • 我不知道你崩溃的真正原因是什么,所以我不会发布答案,但我会尽力回答你的两个问题。关于 1),我假设为您的节点分配不同的物理体会导致原始物理体被解除关联。关于 2),节点属性是弱且可选的(为了避免与拥有节点的引用循环,我假设)。 SKPhysicsBody 的初始化器不将节点作为参数;您将创建的主体传递给节点的 physicsBody 属性。我相信这样做会相应地设置 body 的 node 属性。
  • 尽管如此,我会假设传递给您的方法的contact(它是某种碰撞委托吗?)不包含分离的物理实体(即不属于节点的实体);有什么意义?
  • @NicolasMiari 准确地说,分离的身体有什么意义?因此对正在发生的事情感到困惑!有什么建议吗?
  • 我认为没有意义;由于对象的初始化方式和 API 的设置方式,这在逻辑上是可能的。
  • 也许你可以继承SKNode和/或SKPhysicsBody,用观察者覆盖涉及的属性并尝试捕捉节点何时变为nil

标签: ios sprite-kit skphysicsbody sknode skphysicscontact


【解决方案1】:

SKSPhysicsBody 本身就是一个对象,完全可以被创建但不与 SKSpriteNode 关联(尽管可能没有多大用处:-))

在您的didBallTileHit() 中,您有removeFromParent() 中的任何节点吗?如果是这样,这可能是您崩溃的原因,因为 Sprite-Kit 在 2 个对象之间产生了多次冲突,并且为 2 个节点多次调用 didBegin()。如果您随后在第一次调用 didBegin() 时删除其中一个节点,那么第二次和后续调用将不会出现该节点。

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

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

【讨论】:

  • 这似乎是罪魁祸首!将测试并报告,非常感谢!
【解决方案2】:

您可以通过不同的方式处理联系人。

对你来说更简单的方法是这样写:

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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    相关资源
    最近更新 更多