iOS ARKit+;SceneKit物理接触检测缩放问题

iOS ARKit+;SceneKit物理接触检测缩放问题,ios,scenekit,game-physics,arkit,Ios,Scenekit,Game Physics,Arkit,我有一个简单的3d区域,包含4面墙,每面墙都是一个带有简单SCNBox几何体的SCNNode,为矩形,并连接了匹配的SCNPhysicsBody。SCNPPhysisBody使用SCNPPhysisShape.ShapeType.boundingBox,并设置为静态类型。以下是一段代码片段: let size = (self.levelNode.boundingBox.max - self.levelNode.boundingBox.min) * self.levelNode.s

我有一个简单的3d区域,包含4面墙,每面墙都是一个带有简单SCNBox几何体的SCNNode,为矩形,并连接了匹配的SCNPhysicsBody。SCNPPhysisBody使用SCNPPhysisShape.ShapeType.boundingBox,并设置为静态类型。以下是一段代码片段:

        let size = (self.levelNode.boundingBox.max - self.levelNode.boundingBox.min) * self.levelNode.scale

        //x //z
        let geometryA = SCNBox(width: CGFloat(size.x), height: CGFloat(1 * self.levelNode.scale.x), length: 0.01, chamferRadius: 0)
        let geometryB = SCNBox(width: CGFloat(size.z), height: CGFloat(1 * self.levelNode.scale.x), length: 0.01, chamferRadius: 0)

        geometryA.firstMaterial?.diffuse.contents = UIColor(red: 0.0, green: 0.2, blue: 1.0, alpha: 0.65)
        geometryB.firstMaterial?.diffuse.contents = UIColor(red: 0.0, green: 0.2, blue: 1.0, alpha: 0.65)


        let nodeA = SCNNode(geometry: geometryA)
        nodeA.position += self.levelNode.position
        nodeA.position += SCNVector3(0, 0.25 * self.levelNode.scale.y, -size.z/2)
        nodeA.name = "Boundary-01"

        let nodeB = SCNNode(geometry: geometryA)
        nodeB.position += self.levelNode.position
        nodeB.position += SCNVector3(0, 0.25 * self.levelNode.scale.y, size.z/2)
        nodeB.name = "Boundary-03"

        let nodeC = SCNNode(geometry: geometryB)
        nodeC.position += self.levelNode.position
        nodeC.position += SCNVector3(-size.x/2, 0.25 * self.levelNode.scale.y, 0)
        nodeC.eulerAngles = SCNVector3(0, -Float.pi/2, 0)
        nodeC.name = "Boundary-02"

        let nodeD = SCNNode(geometry: geometryB)
        nodeD.position += self.levelNode.position
        nodeD.position += SCNVector3(size.x/2, 0.25 * self.levelNode.scale.y, 0)
        nodeD.eulerAngles = SCNVector3(0, Float.pi/2, 0)
        nodeD.name = "Boundary-04"

        let nodes = [nodeA, nodeB, nodeC, nodeD]

        for node in nodes {
            //
            let shape = SCNPhysicsShape(geometry: node.geometry!, options: [
                SCNPhysicsShape.Option.type : SCNPhysicsShape.ShapeType.boundingBox])
            let body = SCNPhysicsBody(type: .static, shape: shape)
            node.physicsBody = body
            node.physicsBody?.isAffectedByGravity = false
            node.physicsBody?.categoryBitMask = Bitmask.boundary.rawValue
            node.physicsBody?.contactTestBitMask = Bitmask.edge.rawValue
            node.physicsBody?.collisionBitMask = 0

            scene.rootNode.addChildNode(node)
            node.physicsBody?.resetTransform()
        }
在这个区域内,我以固定的时间间隔生成实体。每个都有一个SCNBox几何体,这次是一个立方体形状,比墙小,物理体的参数与上面相同

为了简化我的实体在这个游戏区域内的行为,我正在计算它们的移动路径,然后对相关节点应用一个命令来移动它们。SCNAction移动节点和连接到它的物理体

我正在使用SCNPhysicsWorld联系人委托来检测实体何时到达某个边界墙。然后,我计算出它从那堵墙往另一个方向的随机轨迹,清除它的动作,然后应用一个新的移动动作

这就是它变得有趣的地方

当这个“世界”的比例为1:1时。在标准SCNScene和使用ARKit投影的场景中,触点均被检测为正常。可见接触,即实体方向上的可见变化似乎如预期的那样接近边界。当我检查每个触点的触点穿透距离时,其值为0.00294602662324905

但当我把这个“世界”的尺度改小一些,比如说10厘米宽,用ARKit表示时,模拟就崩溃了

当检测到实体和边界节点之间的接触时,它们之间具有相对较大的可见间隙。然而,接触穿透距离的大小与以前相同

我打开了ARSCNView调试选项来显示渲染中的物理图形,它们看起来都是正确的比例,与节点的边界框相匹配

正如您可以从上面的代码示例中看到的,边界节点是在我缩放级别之后,在AR用户设置期间生成的。它们将添加到场景的根节点,而不是作为级别节点的子节点。相同的代码用于生成实体

之前,我曾尝试在物理体上使用resetTransform()函数,但在缩放标高后,这并没有生成物理体的可靠缩放,因此我决定在缩放标高后为边界和实体生成节点

在苹果的文档中,它确实指出,如果SCNPhysicsBody不是自定义形状,它将采用应用于它的节点几何体的比例。我不受此影响,因为在将缩放应用到标高后,我正在生成几何体及其各自的节点

目前的一个假设是,物理模拟在如此小的规模下崩溃。但我不是靠模拟力来移动物体

有没有更合适的方法来衡量物理世界

或者,我正在盯着SCNP物理世界中的一个bug,这是我目前无法控制的


我确实考虑过的一个解决方案是以1:1的比例运行整个模拟,但隐藏,然后将这些移动应用于较小的实体。可以想象,这将影响整个场景的性能…

第一次接触的穿透距离为负值,表明存在间隙。当您缩小模拟的大小时,该间隙似乎不会缩小


为了解决上述多余的问题,我对Contact Delegate中的联系人进行了额外的检查,以避免检测到特定类别的第一个联系人,而是确保“穿透距离”值为正值,从而确保两个对象之间存在重叠,在触发与边界相连的实体方向的更改之前

您的意思是,在创建节点并连接其SCNPhysicsBody之后,您正在更改节点的比例吗?@drewster我正在以所需的比例创建节点,然后将物理实体应用于它们,然后将它们添加到场景中。在上面的“我的边界”代码中,我使用其边界框“最小”和“最大”计算标高的大小,并应用其比例,就像在场景中一样。