ARkit 中未检测到 SceneKit 碰撞
SceneKit collision not detected in ARkit
我正在尝试使用 ARkit 和 SceneKit 构建游戏,但是在设置物理世界委托和对象的物理体之后,委托方法 didBeginContact 没有被调用。
这是我的物理体结构
struct CollisionCategory {
static let moltenBullet :Int = 4
static let iceShield :Int = 8
}
这是我设置物理体的方式
let collisionShape = SCNPhysicsShape(node: node, options: nil)
self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: collisionShape)
self.physicsBody?.categoryBitMask = self.categoryMask
self.physicsBody?.contactTestBitMask = self.collisionMask
self.physicsBody?.collisionBitMask = self.collisionMask
我使用self是因为它是一个自定义class的物理体,继承自SCNNode,collisionMask和categoryMask是在使用上述结构的构造函数中设置的。
在 didBeginContact 中,我想打印一些东西,但没有任何反应。
我已经将 SCNPhysicsContactDelegate 设置为
sceneView.scene.physicsWorld.contactDelegate
sceneView 是 ARSCNView。
我用
正确地看到了 physicsBody 的形状
SCNDebugOptionShowPhysicsShape
为什么会这样?
您的节点不会相互交互,因为它们属于不同的类别。
以下是 collsionBitMask
根据 the documentation 工作的方式:
When two physics bodies contact each other, a collision may occur. SceneKit compares the body’s collision mask to the other body’s category mask by performing a bitwise AND operation. If the result is a nonzero value, then the body is affected by the collision.
contactBitMask
和 categoryBitMask
的工作原理相同。
当 SceneKit 检查您的 physicsBody 是否有接触时,会发生以下情况:
object1.physicsBody.contactTestBitMask = 4 = 0100b
object2.physicsBody.categoryBitMask = 8 = 1000b
-----
(bitwise AND) 0000b = 0 -> no collision
定义类别的最佳方法是使用 OptionSet
, Apple actually provides you with default categories in SCNPhysicsCollisionCategory
。
如果您希望两个节点或 physicsBody 进行交互,它们需要共享至少一个类别。否则不会碰撞。
您的示例可能如下所示:
struct CollisionCategory: OptionSet {
let rawValue: Int
static let moltenBullet = CollisionCategory(rawValue: 4)
static let iceWall = CollisionCategory(rawValue : 8)
}
然后你像这样分配你的类别:
class Bullet: SCNNode {
...
// The physics body-category is a bullet
self.physicsBody?.categoryBitMask = CollisionCategory.moltenBuller.rawValue
// This contacts with both other bullets and ice walls!
self.physicsBody?.contactBitMask = [CollsionCategory.moltenBullet, CollisionCategory.iceWall].rawValue
self.physicsBody?.collisionBitMask = self.physicsBody!.contactBitMask
}
我正在尝试使用 ARkit 和 SceneKit 构建游戏,但是在设置物理世界委托和对象的物理体之后,委托方法 didBeginContact 没有被调用。
这是我的物理体结构
struct CollisionCategory {
static let moltenBullet :Int = 4
static let iceShield :Int = 8
}
这是我设置物理体的方式
let collisionShape = SCNPhysicsShape(node: node, options: nil)
self.physicsBody = SCNPhysicsBody(type: .dynamic, shape: collisionShape)
self.physicsBody?.categoryBitMask = self.categoryMask
self.physicsBody?.contactTestBitMask = self.collisionMask
self.physicsBody?.collisionBitMask = self.collisionMask
我使用self是因为它是一个自定义class的物理体,继承自SCNNode,collisionMask和categoryMask是在使用上述结构的构造函数中设置的。
在 didBeginContact 中,我想打印一些东西,但没有任何反应。 我已经将 SCNPhysicsContactDelegate 设置为
sceneView.scene.physicsWorld.contactDelegate
sceneView 是 ARSCNView。
我用
正确地看到了 physicsBody 的形状SCNDebugOptionShowPhysicsShape
为什么会这样?
您的节点不会相互交互,因为它们属于不同的类别。
以下是 collsionBitMask
根据 the documentation 工作的方式:
When two physics bodies contact each other, a collision may occur. SceneKit compares the body’s collision mask to the other body’s category mask by performing a bitwise AND operation. If the result is a nonzero value, then the body is affected by the collision.
contactBitMask
和 categoryBitMask
的工作原理相同。
当 SceneKit 检查您的 physicsBody 是否有接触时,会发生以下情况:
object1.physicsBody.contactTestBitMask = 4 = 0100b
object2.physicsBody.categoryBitMask = 8 = 1000b
-----
(bitwise AND) 0000b = 0 -> no collision
定义类别的最佳方法是使用 OptionSet
, Apple actually provides you with default categories in SCNPhysicsCollisionCategory
。
如果您希望两个节点或 physicsBody 进行交互,它们需要共享至少一个类别。否则不会碰撞。
您的示例可能如下所示:
struct CollisionCategory: OptionSet {
let rawValue: Int
static let moltenBullet = CollisionCategory(rawValue: 4)
static let iceWall = CollisionCategory(rawValue : 8)
}
然后你像这样分配你的类别:
class Bullet: SCNNode {
...
// The physics body-category is a bullet
self.physicsBody?.categoryBitMask = CollisionCategory.moltenBuller.rawValue
// This contacts with both other bullets and ice walls!
self.physicsBody?.contactBitMask = [CollsionCategory.moltenBullet, CollisionCategory.iceWall].rawValue
self.physicsBody?.collisionBitMask = self.physicsBody!.contactBitMask
}