SpriteKit Swift: 当 bodyA 同时与多个 body 碰撞时如何防止崩溃?
SpriteKit Swift: How to prevent a Crash when bodyA collisions with more than one bodyB at the same time?
情况:
已经广泛搜索,没有找到解决方案。
例如,这没有帮助:Swift/SpriteKit Multiple Collision Detection?
问题:
我的代码工作正常,除非玩家同时击中两个不同的 PhysicsCategory 对象(例如,掉落并同时准确击中地面和墙壁)。这会使我的应用程序崩溃。
代码:
struct PhysicsCategory {
static let player: UInt32 = 0x1 << 1
static let ground: UInt32 = 0x1 << 2
static let wall: UInt32 = 0x1 << 3
static let scoreWall: UInt32 = 0x1 << 4
}
func didBeginContact(contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == PhysicsCategory.scoreWall && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.scoreWall {
score += 1
scoreLabel.text = "\(score)"
updatePlayerColor()
}
else if firstBody.categoryBitMask == PhysicsCategory.wall && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.wall {
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
//playDeathAnimation with completion block self.dismiss(VC)
}
else if firstBody.categoryBitMask == PhysicsCategory.ground && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.ground {
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
//playDeathAnimation with completion block self.dismiss(VC)
}
}
调试器错误:
致命错误:索引超出范围。
我要找的是:
我只想知道我的代码中是否已经考虑了双重碰撞。调试器错误是指我的代码中受冲突影响的其他部分。但是这里添加的代码太多了。所以请只回答以下问题:如何解释我的 SpriteKit 游戏中 ScoreWall 和 Wall 之间的双重碰撞?
试试这样的东西?它应该删除您的代码重复并防止您的游戏结束逻辑发生两次。
func didBeginContact(contact: SKPhysicsContact) {
if (lost) {
return
}
var a = contact.bodyA.categoryBitMask
var b = contact.bodyB.categoryBitMask
if a > b {
swap(&a, &b)
}
if a == PhysicsCategory.player && b == PhysicsCategory.scoreWall {
score += 1
scoreLabel.text = "\(score)"
updatePlayerColor()
} else if a == PhysicsCategory.player && (b == PhysicsCategory.ground || b == PhysicsCategory.wall) {
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
//playDeathAnimation with completion block self.dismiss(VC)
}
}
你遇到了什么错误?
无论如何,你可能要等到物理模拟结束后才能删除重要部分(不知道你的应用程序的整个逻辑)。因此在碰撞检测中设置 lost
布尔条件是好的,但其余的可能必须在 didSimulatePhysics
或 didFinishUpdate
.
中完成
您没有发生双重碰撞。你将有 2 次单次碰撞,即 didBeginContact
将被调用一次用于玩家与地面之间的碰撞,再次用于玩家与墙壁之间的碰撞。一个 SKPhysicsContact
只能有 2 个主体。您的崩溃是由其他原因引起的,可能是由于删除了 gameVC?
有关 didBeginContact
的 'cleaner' 版本的示例,试试这个:
func didBeginContact(contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
// If the player and the scoreWall have collided:
case .player | .scoreWall :
score += 1
scoreLabel.text = "\(score)"
updatePlayerColor()
// If the player and the wall have collided:
case .player | .wall :
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
// If the player and the ground have collided:
case .player | .ground :
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
default :
print("Some other contact has occurred")
}
情况:
已经广泛搜索,没有找到解决方案。
例如,这没有帮助:Swift/SpriteKit Multiple Collision Detection?
问题:
我的代码工作正常,除非玩家同时击中两个不同的 PhysicsCategory 对象(例如,掉落并同时准确击中地面和墙壁)。这会使我的应用程序崩溃。
代码:
struct PhysicsCategory {
static let player: UInt32 = 0x1 << 1
static let ground: UInt32 = 0x1 << 2
static let wall: UInt32 = 0x1 << 3
static let scoreWall: UInt32 = 0x1 << 4
}
func didBeginContact(contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == PhysicsCategory.scoreWall && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.scoreWall {
score += 1
scoreLabel.text = "\(score)"
updatePlayerColor()
}
else if firstBody.categoryBitMask == PhysicsCategory.wall && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.wall {
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
//playDeathAnimation with completion block self.dismiss(VC)
}
else if firstBody.categoryBitMask == PhysicsCategory.ground && secondBody.categoryBitMask == PhysicsCategory.player || firstBody.categoryBitMask == PhysicsCategory.player && secondBody.categoryBitMask == PhysicsCategory.ground {
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
//playDeathAnimation with completion block self.dismiss(VC)
}
}
调试器错误:
致命错误:索引超出范围。
我要找的是:
我只想知道我的代码中是否已经考虑了双重碰撞。调试器错误是指我的代码中受冲突影响的其他部分。但是这里添加的代码太多了。所以请只回答以下问题:如何解释我的 SpriteKit 游戏中 ScoreWall 和 Wall 之间的双重碰撞?
试试这样的东西?它应该删除您的代码重复并防止您的游戏结束逻辑发生两次。
func didBeginContact(contact: SKPhysicsContact) {
if (lost) {
return
}
var a = contact.bodyA.categoryBitMask
var b = contact.bodyB.categoryBitMask
if a > b {
swap(&a, &b)
}
if a == PhysicsCategory.player && b == PhysicsCategory.scoreWall {
score += 1
scoreLabel.text = "\(score)"
updatePlayerColor()
} else if a == PhysicsCategory.player && (b == PhysicsCategory.ground || b == PhysicsCategory.wall) {
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
//playDeathAnimation with completion block self.dismiss(VC)
}
}
你遇到了什么错误?
无论如何,你可能要等到物理模拟结束后才能删除重要部分(不知道你的应用程序的整个逻辑)。因此在碰撞检测中设置 lost
布尔条件是好的,但其余的可能必须在 didSimulatePhysics
或 didFinishUpdate
.
您没有发生双重碰撞。你将有 2 次单次碰撞,即 didBeginContact
将被调用一次用于玩家与地面之间的碰撞,再次用于玩家与墙壁之间的碰撞。一个 SKPhysicsContact
只能有 2 个主体。您的崩溃是由其他原因引起的,可能是由于删除了 gameVC?
有关 didBeginContact
的 'cleaner' 版本的示例,试试这个:
func didBeginContact(contact: SKPhysicsContact) {
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
// If the player and the scoreWall have collided:
case .player | .scoreWall :
score += 1
scoreLabel.text = "\(score)"
updatePlayerColor()
// If the player and the wall have collided:
case .player | .wall :
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
// If the player and the ground have collided:
case .player | .ground :
lost = true
self.scene?.speed = 0
gameVC?.dismissViewControllerAnimated(false, completion: nil)
default :
print("Some other contact has occurred")
}