How to Detect collision in Swift, Sprite kit
- Define unique categories, ensure your class is a
SKPhysicsContactDelegate
and make yourself the physics contact delegate:
//Physics categories
let enemyCategory: UInt32 = 1 << 1
let bulletCategory: UInt32 = 1 << 2
class GameScene: SKScene, SKPhysicsContactDelegate {
physicsWorld.contactDelegate = self
Assign the categories (usually in
didMove(to view:)
:enemy.physicsBody.catgeoryBitMask = enemyCategory
bullet.physicsBody.catgeoryBitMask = bulletCategory
(Make sure you've created physics bodies for each node)
- Set up collisions:
enemy.physicsBody?.collisionBitMask = 0 // enemy collides with nothing
bullet.physicsBody?.collisionBitMask = 0 // bullet collides with nothing
or even:
for node in [enemy, bullet] {
node.physicsBody?.collisionBitMask = 0 // collides with nothing
}
Set up contacts
bullet.physicsBody?.collisionBitMask = enemyCategory // bullet contacts enemy
Make sure that at least one of the objects involved in each potential contact has the isDynamic
property on its physics body set to true
, or no contact will be generated. It is not necessary for both of the objects to be dynamic.
You should now get didBegin
called when the bullet and the enemy make contact. You could code didBegin
like this:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case bulletCategory | enemyCategory:
print("bullet and enemy have contacted.")
let bulletNode = contact.bodyA.categoryBitMask == bulletCategory ? contact.bodyA.node : contact.bodyB.node
enemyHealth -= 10
bulletNode.removeFromParent
default:
print("Some other contact occurred")
}
}
SpriteKit Collision Detection Not Working Properly
- Define unique categories, ensure your class is a
SKPhysicsContactDelegate
and make yourself the physics contact delegate:
//Physics categories
let appleCategory: UInt32 = 1 << 0
let enemyCategory: UInt32 = 1 << 1
let bulletCategory: UInt32 = 1 << 2
class GameScene: SKScene, SKPhysicsContactDelegate {
physicsWorld.contactDelegate = self
Assign the categories (usually in
didMove(to view:)
:apple.physicsBody.catgeoryBitMask = appleCategory
enemy.physicsBody.catgeoryBitMask = enemyCategory
bullet.physicsBody.catgeoryBitMask = bulletCategory
(Make sure you've created physics bodies for each node)
- Set up collisions:
apple.physicsBody?.collisionBitMask = 0 // apple/player collides with nothing
enemy.physicsBody?.collisionBitMask = 0 // enemy collides with nothing
bullet.physicsBody?.collisionBitMask = 0 // bullet collides with nothing
or even:
for node in [apple, enemy, bullet] {
node.physicsBody?.collisionBitMask = 0 // collides with nothing
}
Set up contacts
bullet.physicsBody?.collisionBitMask = enemyCategory // bullet contacts enemy
Make sure that at least one of the objects involved in each potential contact has the isDynamic
property on its physics body set to true
, or no contact will be generated. It is not necessary for both of the objects to be dynamic.
You should now get didBegin
called when the bullet and the enemy make contact. You could code didBegin
like this:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case bulletCategory | enemyCategory:
print("bullet and enemy have contacted.")
let bulletNode = contact.bodyA.categoryBitMask == bulletCategory ? contact.bodyA.node : contact.bodyB.node
enemyHealth -= 10
bulletNode.removeFromParent
default:
print("Some other contact occurred")
}
}
Collision Detection In Sprite Kit Swift
physicsBody!.isDynamic = false
means that no physics activity will happen to this body. Other bodies can interact with it, but it will not interact with anything.
This makes sense for a pipe to have, because a pipe never moves, so there is no reason to be dynamic. (Your world should be moving, not the pipe, if you are doing a flappy bird-esc game)
Now for Mario, this does not make sense. Mario is a moving entity, so he will be interacting with the physics world around in. To fix your issue, you need to make him dynamic with mario.physicsBody!.isDynamic = true
Related Topics
In Swift, How to Avoid Both Optionals and Nil Object References
How to Create a Circular Progress Indicator for a Count Down Timer
In Swift, Array [String] Slicing Return Type Doesn't Seem to Be [String]
iOS 7 Sprite Kit Freeing Up Memory
Select Multiple Images (Uiimagepickercontroller or Photos.App Share Ui)
Swift 2.0 Calendar Components Error
Undefined Symbols for Architecture X86_64 on Xcode 6.1
How to Recognize Which Pin Was Tapped
Uitableview and Uiview with Keyboardwillshow
Iad Is Shutting Down. Should I Remove the Iad Framework from All My Applications
Update Restkit 'Lcl_Rk.H' File Not Found in Rklog.H
Uitableview Load More When Scrolling to Bottom Like Facebook Application
Behaviour for Significant Change Location API When Terminated/Suspended
How to Create a Delay in Swift
"From View Controller" Disappears Using Uiviewcontrollercontexttransitioning
Prompt When Trying to Dial a Phone Number Using Tel:// Scheme on iOS 10.3