答案的线索在你if let
陈述的开头。
让我们分解一下:
当您说 时let anchor = sceneView.session.currentFrame?.anchors.first
,您是在引用一个可选数组ARAnchor
,它自然可以有多个元素。
由于您总是调用first
例如索引 [0],因此您将始终获得ARAnchor
添加到数组中的第一个。
由于您现在有 2 个锚点,因此您自然需要最后一个(最新的)元素。因此,您可以尝试以下方法:
if let anchor = sceneView.session.currentFrame?.anchors.last {
let node = sceneView.node(for: anchor)
addNode(position: SCNVector3Zero, anchorNode: node)
} else {
debugPrint("anchor node is nil")
}
更新:
由于另一位发帖者对这个问题的解释不同,他们认为问题是如何检测 ARPlaneAnchor 是否在视野中?让我们以另一种方式处理它。
首先,我们需要考虑到 ARCamera 有一个 Frostrum,其中显示了我们的内容:
因此,我们需要确定 ARPlaneAnchor 是否为inViewOfFrostrum
.
首先,我们将创建 2 个变量:
var planesDetected = [ARPlaneAnchor: SCNNode]()
var planeID: Int = 0
第一个用于存储ARPlaneAnchor
及其关联SCNNode
的 ,第二个用于为每个平面提供唯一的 ID。
在中ARSCNViewDelegate
我们可以可视化一个 ARPlaneAnchor,然后存储它的信息,例如:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
//1. Get The Current ARPlaneAnchor
guard let anchor = anchor as? ARPlaneAnchor else { return }
//2. Create An SCNode & Geometry To Visualize The Plane
let planeNode = SCNNode()
let planeGeometry = SCNPlane(width: CGFloat(anchor.extent.x), height: CGFloat(anchor.extent.z))
planeGeometry.firstMaterial?.diffuse.contents = UIColor.cyan
planeNode.geometry = planeGeometry
//3. Set The Position Based On The Anchors Extent & Rotate It
planeNode.position = SCNVector3(anchor.center.x, anchor.center.y, anchor.center.z)
planeNode.eulerAngles.x = -.pi / 2
//4. Add The PlaneNode To The Node & Give It A Unique ID
node.addChildNode(planeNode)
planeNode.name = String(planeID)
//5. Store The Anchor & Node
planesDetected[anchor] = planeNode
//6. Increment The Plane ID
planeID += 1
}
现在我们已经存储了检测到的平面,我们当然需要确定其中是否有任何一个在 ARCamera 的视图中,例如:
/// Detects If An Object Is In View Of The Camera Frostrum
func detectPlaneInFrostrumOfCamera(){
//1. Get The Current Point Of View
if let currentPointOfView = augmentedRealityView.pointOfView{
//2. Loop Through All The Detected Planes
for anchorKey in planesDetected{
let anchor = anchorKey.value
if augmentedRealityView.isNode(anchor, insideFrustumOf: currentPointOfView){
print("ARPlaneAnchor With ID \(anchor.name!) Is In View")
}else{
print("ARPlaneAnchor With ID \(anchor.name!) Is Not In View")
}
}
}
}
最后我们需要访问这个函数,我们可以用下面的delegate
方法来做,例如renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
:
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
detectPlaneInFrostrumOfCamera()
}
希望这两个都指向正确的方向......