SpriteKit 崩溃:物理体如何失去与 SKNode 的关联?
SpriteKit crash: how can physics body lose association with SKNode?
此代码崩溃,因为 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) 没有节点的物理体怎么可能存在?
SKSPhysicsBody 本身就是一个对象,完全可以创建但不与 SKSpriteNode 关联(尽管可能用处不大 :-))
在您的 didBallTileHit()
中,您 removeFromParent()
有任何节点吗?如果是这样,这可能是您崩溃的原因,因为 Sprite-Kit 在 2 个对象之间产生了多次碰撞,并且为 2 个节点多次调用 didBegin()
。如果您随后在对 didBegin()
的第一次调用中删除其中一个节点,则在第二次和后续调用中它不会存在。
处理它的方法(在某些情况下你不能让 sprite-kit 多次调用 didBegin)是确保你的联系代码适应这个并且多次处理合同不会导致问题(例如多次添加到分数、删除多个生命、尝试访问已删除的节点或物理体等)。
有关更多详细信息和可能的解决方案,请参阅此答案:
您可以通过不同的方式处理联系人。
对你来说更简单的方法是这样写:
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
}
此代码崩溃,因为 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) 没有节点的物理体怎么可能存在?
SKSPhysicsBody 本身就是一个对象,完全可以创建但不与 SKSpriteNode 关联(尽管可能用处不大 :-))
在您的 didBallTileHit()
中,您 removeFromParent()
有任何节点吗?如果是这样,这可能是您崩溃的原因,因为 Sprite-Kit 在 2 个对象之间产生了多次碰撞,并且为 2 个节点多次调用 didBegin()
。如果您随后在对 didBegin()
的第一次调用中删除其中一个节点,则在第二次和后续调用中它不会存在。
处理它的方法(在某些情况下你不能让 sprite-kit 多次调用 didBegin)是确保你的联系代码适应这个并且多次处理合同不会导致问题(例如多次添加到分数、删除多个生命、尝试访问已删除的节点或物理体等)。
有关更多详细信息和可能的解决方案,请参阅此答案:
您可以通过不同的方式处理联系人。
对你来说更简单的方法是这样写:
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
}