我在碰撞检测方面遇到问题。
1)我用ViewController
扩展了SCNPhysicsContactDelegate
类:
class ViewController: UIViewController, SCNPhysicsContactDelegate
2)我设置了一个OptionSet来管理碰撞类别:
// Collisions
struct CollisionCategory: OptionSet {
let rawValue: Int
static let CoinsCategory = CollisionCategory(rawValue: 0) // Coin SCNNode
static let CarCategory = CollisionCategory(rawValue : 1) // Car SCNNode
static let FinishLineCategory = CollisionCategory(rawValue: 2) // FinishLine SCNNode
}
3)我设置了所有的categoryBitMask
,contactTestBitMask
和collisionBitMask
:
// Setup car
carNode.physicsBody?.categoryBitMask = CollisionCategory.CarCategory.rawValue
carNode.physicsBody?.contactTestBitMask = CollisionCategory.CoinsCategory.rawValue | CollisionCategory.FinishLineCategory.rawValue
carNode.physicsBody?.collisionBitMask = CollisionCategory.CoinsCategory.rawValue | CollisionCategory.FinishLineCategory.rawValue
// Setup finishLine
planeNode.physicsBody?.categoryBitMask = CollisionCategory.FinishLineCategory.rawValue
planeNode.physicsBody?.contactTestBitMask = CollisionCategory.CarCategory.rawValue
planeNode.physicsBody?.collisionBitMask = CollisionCategory.CarCategory.rawValue
// Setup coin
coin.physicsBody?.categoryBitMask = CollisionCategory.CoinsCategory.rawValue
coin.physicsBody?.contactTestBitMask = CollisionCategory.CarCategory.rawValue
coin.physicsBody?.collisionBitMask = CollisionCategory.CarCategory.rawValue
4)我将physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact)
设置为在发生碰撞时进行管理:
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
if(contact.penetrationDistance >= 0.08 && contact.nodeB.name!.contains("Coin")) {
// Remove coin from parent
contact.nodeB.removeFromParentNode()
// Increment counter
self.coinsCounter += 1
DispatchQueue.main.async {
// Increase coin counter
let view = self.arSceneView.viewWithTag(10) as! UILabel
view.text = String(self.coinsCounter)
}
}
// PROBLEMS HERE
if(contact.penetrationDistance >= 0.076 && contact.nodeB.name!.contains("FinishLine") && !self.startFinishLineCollision && !self.outOfTrack) {
self.startFinishLineCollision = true
// Increment lap
if(seconds > 10) {
self.laps += 1
DispatchQueue.main.async {
(self.arSceneView.viewWithTag(14) as! UILabel).text = String(self.laps)
}
if(self.laps == 4){
endGame()
}
}
}
}
我需要检查汽车何时到达终点线以标记一个圈并将圈数计数器加1。问题是,即使有nodeA
和nodeB
,我也不断收到此功能的联系消息汽车与终点线之间没有碰撞。
例如,在下图中,有碰撞消息,但汽车与终点线之间没有有效的碰撞。
当前设置有什么问题?
我需要检查汽车和终点线之间是否有精确的碰撞。
谢谢
我也尝试了以下设置,但没有解决方法...
let CoinsCategory = 2
let CarCategory = 4
let FinishLineCategory = 6
carNode.physicsBody?.categoryBitMask = CarCategory
carNode.physicsBody?.collisionBitMask = CoinsCategory | FinishLineCategory
planeNode.physicsBody?.categoryBitMask = FinishLineCategory
planeNode.physicsBody?.collisionBitMask = CarCategory
coin.physicsBody?.categoryBitMask = CoinsCategory
coin.physicsBody?.collisionBitMask = CarCategory
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
switch contact.nodeB.physicsBody!.collisionBitMask {
case FinishLineCategory:
print("Finish Line Collision")
case CoinsCategory:
print("Coin Collision")
default:
print("Other collision")
}
}
没有印刷品被称为...就像物体之间没有碰撞。
NOTE:终点线,汽车和硬币都是同一父级(子级下面的平面)上的所有子级。有关系吗?
好,我找到了解决此问题的方法:
1)我用一枚硬币(黄色立方体)作为对撞机。
2)用Color.clear
(透明色)设置它以使其不可见。
3)我将其放置在终点线的中心。
4)由于contactTest
不起作用,我使用了penetrationDistance
:
func physicsWorld(_ world: SCNPhysicsWorld, didBegin contact: SCNPhysicsContact) {
if(contact.penetrationDistance >= 0.08 && contact.nodeB.name! == "Coin") {
// Remove coin from parent
contact.nodeB.removeFromParentNode()
// Increment counter
self.coinsCounter += 1
DispatchQueue.main.async {
// Increase coin counter
let view = self.arSceneView.viewWithTag(10) as! UILabel
view.text = String(self.coinsCounter)
}
}
// >>>>> NEW CODE HERE! <<<<<
if(contact.penetrationDistance > 0.078 && contact.nodeB.name! == "CoinFinishLine" && !self.outOfTrack && !self.lapIncrement) {
self.lapIncrement = true
// Start lap increment timer (5 seconds)
self.startNSecondsTimer(howMuchTime: 1.0, target: 1)
// Increment lap
if(seconds > 10) {
self.laps += 1
DispatchQueue.main.async {
(self.arSceneView.viewWithTag(14) as! UILabel).text = String(self.laps)
}
if(self.laps == 3){
endGame()
}
}
}
}
无论如何,如果有人可以向我解释为什么我不能使contactTestBitMask
正常工作,而我只能使用collisionBitMask
来解决此问题,那是值得欢迎的。谢谢