在 ARkit 中未检测到 SceneKit 碰撞

Posted

技术标签:

【中文标题】在 ARkit 中未检测到 SceneKit 碰撞【英文标题】:SceneKit collision not detected in ARkit 【发布时间】:2018-02-15 21:06:33 【问题描述】:

我正在尝试使用 ARkit 和 SceneKit 构建游戏,但是在设置了physicsWorld 委托和对象的物理主体之后,委托方法 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是因为它是一个继承自SCNNode的自定义类的物理体,collisionMask和categoryMask是使用上面的struct在构造函数中设置的。

在 didBeginContact 中,我想打印一些东西,但什么也没发生。 我已经将 SCNPhysicsContactDelegate 设置为

sceneView.scene.physicsWorld.contactDelegate

sceneView 是 ARSCNView。

我正确地看到了physicsBody的形状

SCNDebugOptionShowPhysicsShape

为什么会这样?

【问题讨论】:

您是否希望两个具有相同CollisionCategory 的对象或子弹和盾牌发生碰撞? 对象是这样声明的 object1(category: object1, collision: object2), object2(category: object2, collision: object1) 对不起,是的!我预计子弹和盾牌会碰撞 【参考方案1】:

您的节点不会相互交互,因为它们属于不同的类别。 以下是collsionBitMask 根据the documentation 的工作方式:

当两个物理体相互接触时,可能会发生碰撞。 SceneKit 通过执行按位与操作将 body 的碰撞掩码其他 body 的类别掩码 进行比较。如果结果是一个非零值,那么身体会受到碰撞的影响。

contactBitMaskcategoryBitMask 的工作方式相同。

当 SceneKit 检查您的physicsBody 是否有联系人时,会发生以下情况:

object1.physicsBody.contactTestBitMask = 4 = 0100b
object2.physicsBody.categoryBitMask    = 8 = 1000b
                                             -----
                               (bitwise AND) 0000b = 0 -> no collision

定义类别的最佳方式是使用OptionSet,Apple 实际上在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 碰撞的主要内容,如果未能解决你的问题,请参考以下文章

ARKit + SceneKit:我可以访问帧的分段缓冲区但禁用自动人物遮挡吗?

如何设置 SceneKit 碰撞检测

didBeginContact 委托方法未触发 ARKit 碰撞检测

在方法 OnCollisonEnter2D 中未检测到碰撞

如何在 iOS 11 中将 SKVideoNode 添加到 ARKit-SceneKit?

将孩子添加到场景 ARKit/SceneKit 时 FPS 下降