Reputation: 71
I'm trying to setup collision detection between SCNNodes but I'm having problems.
As first step I have setup my class to extend SCNPhysicsContactDelegate
:
class ViewController: SCNPhysicsContactDelegate
.
.
.
self.arSceneView.scene.physicsWorld.contactDelegate = self
I have 2 type of SCNNodes: a car and coins. For both I have setup a collision category:
// Collisions
struct CollisionCategory: OptionSet {
let rawValue: Int
static let CoinsCategory = CollisionCategory(rawValue: 4)
static let CarCategory = CollisionCategory(rawValue : 8)
}
Both have also a physicsBody assigned and to each of them I assigned the category and kind of interaction element.
Car
// Create physics shape
let boxBodyShape = SCNPhysicsShape(node: carNode, options: nil)
// Create physics body
let boxBody = SCNPhysicsBody(type: .kinematic, shape: boxBodyShape)
// Assign physics body
carNode.physicsBody = boxBody
// Setup category collisions properties
carNode.physicsBody?.categoryBitMask = CollisionCategory.CarCategory.rawValue
carNode.physicsBody?.contactTestBitMask = CollisionCategory.CoinsCategory.rawValue
carNode.physicsBody?.collisionBitMask = CollisionCategory.CoinsCategory.rawValue
Coin
// Create physics body
let boxBody = SCNPhysicsBody(type: .kinematic, shape: boxBodyShape)
// Assign physics body
coin.physicsBody = boxBody
// Setup category collisions properties
coin.physicsBody?.categoryBitMask = CollisionCategory.CoinsCategory.rawValue
coin.physicsBody?.contactTestBitMask = CollisionCategory.CarCategory.rawValue
coin.physicsBody?.collisionBitMask = CollisionCategory.CarCategory.rawValue
Last step I implemented the function physicsWorld(:didBegan:)
to manage collisions:
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
print("A: \(contact.nodeA.name) - B: \(contact.nodeB.name)")
print("A: \(contact.nodeA.physicsBody!.categoryBitMask) - B: \(contact.nodeB.physicsBody!.categoryBitMask)")
}
All this is working but not as expected. I'm getting a continuous collision of the car with coins in the scene even if there is no collision. The console output is constantly giving me a collision:
...
...
...
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin8")
A: 8 - B: 4
Penetration distance: false
A: Optional("Car") - B: Optional("Coin9")
...
...
...
Following image gives an idea of the scene situation:
I don't understand what is wrong or what is missing into the setup.
It seems like when the car is near some cubes (coins) they influence it and so happens the "collision" but, I don't understand it...
Thank you!
Upvotes: 1
Views: 94
Reputation: 71
Ok, I resolved by adding this control:
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
if(contact.penetrationDistance >= 0.08 && contact.nodeB.name!.contains("Coin")) {
contact.nodeB.removeFromParentNode()
}
}
Upvotes: 1
Reputation: 1213
You might try something like this:
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact)
{
if(data.gameState == .run)
{
guard let nodeNameA = contact.nodeA.name else { return }
guard let nodeNameB = contact.nodeB.name else { return }
if(nodeNameA.prefix(5) == "Explo" && nodeNameB.prefix(5) == "Missi")
{
gameControl.enemyMissileHit(vIndex: Int(nodeNameB.suffix(4))!)
}
if(nodeNameA.prefix(5) == "Missi" && nodeNameB.prefix(5) == "Explo")
{
gameControl.enemyMissileHit(vIndex: Int(nodeNameA.suffix(4))!)
}
if(nodeNameA.prefix(5) == "Explo" && nodeNameB.prefix(5) == "Hive ")
{
gameControl.enemyHiveHit(vIndex: Int(nodeNameB.suffix(4))!)
}
if(nodeNameA.prefix(5) == "Hive " && nodeNameB.prefix(5) == "Explo")
{
gameControl.enemyHiveHit(vIndex: Int(nodeNameA.suffix(4))!)
}
}
}
Upvotes: 0