代码之家  ›  专栏  ›  技术社区  ›  john doe

didaddnode与scenekit冲突检测

  •  0
  • john doe  · 技术社区  · 6 年前

    我正在构建一个小型演示,其中两个对象可以相互碰撞。基本上,一个物体将被放置在一个平面上。我有下面的代码,用于将物理体添加到平面上。

     func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
    
            if anchor is ARPlaneAnchor {
    
    
                let plane = SCNPlane(width: 0.5, height: 0.5)
                let material = SCNMaterial()
                material.isDoubleSided = true
                material.diffuse.contents = UIImage(named: "overlay_grid")
                plane.firstMaterial = material
    
                let planeNode = SCNNode(geometry: plane)
                planeNode.physicsBody = SCNPhysicsBody(type: .static, shape: nil)
                planeNode.physicsBody?.categoryBitMask = BodyType.plane.rawValue
    
                planeNode.eulerAngles.x = .pi/2
    
                node.addChildNode(planeNode)
    
    }
    

    即使添加了平面,它也不参与任何物理碰撞。如果我试着把物体放在上面,它就会穿过它。但如果我将最后一行改为以下行,它会起作用:

    // node.addChildNode(planeNode) // INSTEAD OF THIS
       planeNode.position = SCNVector3(anchor.transform.columns.3.x, anchor.transform.columns.3.y, anchor.transform.columns.3.z)
     self.sceneView.scene.rootNode.addChildNode(planeNode) // THIS WORKS
    

    我的理解是,所有与冲突相关的东西都由sceneview维护,为了参与冲突,我需要将其添加到sceneview层次,而不是arscnview层次。

    问题:

    // node.addChildNode(planeNode) // WHY THIS DOES NOT WORK
       planeNode.position = SCNVector3(anchor.transform.columns.3.x, anchor.transform.columns.3.y, anchor.transform.columns.3.z)
    
     self.sceneView.scene.rootNode.addChildNode(planeNode) // WHY THIS WORKS
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   rickster    6 年前

    static 物理体之所以如此命名是因为它们不应该移动(相对于全局/世界/场景坐标空间)。物理引擎内部工作中的许多优化都依赖于此,因此更改具有附加静态物理体的节点的位置可能会导致错误的行为。

    Arkit不断移动 ARPlaneAnchor 从平面检测的结果来看,从更多不同的角度看一个真实的平面越长,它就越了解平面的位置和大小。

    将子节点添加到 ARSCNView -中的托管节点 renderer(_:didAdd:for:) ,子节点_ position 可能不会改变…但该位置相对于其父节点,arkit会自动移动父节点以匹配 天幕锚 随之而来。因此,只要arkit更新平面定位点,子节点就相对于世界移动。如果你在那个节点上有一个静态物理体,你会感到奇怪。

    直接将节点添加为场景的子级时, rootNode 并设置其位置 基于 这个 最初的 对于飞机锚,该节点保持静止。 你是谁? 唯一一个设置了它的世界空间位置,而你只做了一次。所以给它一个静态物理体是安全的。

    (请注意,如果您希望静态物理体行为能够随时间变化,则可以删除物理体并在新位置重新创建它。只是不要经常这样做,否则您很可能会击败物理引擎中的其他优化。)