在我的应用程序中,我使用 ARKit 的委托方法来自动检测表面/平面:
-
renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {}
添加飞机。 -
renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {}
更新飞机。 -
renderer(_ renderer: SCNSceneRenderer, didRemove node: SCNNode, for anchor: ARAnchor) {}
移除飞机。
我的配置设置为启用水平面检测为:
configuration?.planeDetection = .horizontal
这可以正常工作,并且我能够检测和创建要检测表面的平面节点。
这里有两个问题:
-
根据 Apple docs的规定,如果要停止水平面检测,应该可以将 planeDetection 设置为
[]
。我试图在一个按钮内将 planeDetection 设置为空,但是在运行应用程序时,仍会在应用程序中检测到平面。这意味着renderer(didAdd: )
和renderer(didUpdate: )
方法仍可操作。为了确保我什至打印了它们的结果,并且即使禁用了 planeDetection,它们也可以运行。 难道我做错了什么?随意停止 renderer(didAdd:)和 renderer(didUpdate:)方法的肯定方法是什么? -
在某些情况下,会在同一位置检测到两个平面。有时,这两架飞机会合并,但有时却不会。 **就最佳做法而言,如何避免这种情况?**我尝试检测场景的视锥中是否已经存在一个 planeNode,不添加新的飞机,但是这也带来了一些问题,尤其是当有一个增加了平面,但后来又假定要在同一位置添加另一个平面,而后者是一个正在更新的委托函数。在这种情况下,甚至不添加后者,因为前者仍在我的视锥范围内。希望这很清楚.只是想知道如何最好地避免/避免这种情况?
渲染器方法的主体是通常的:
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else { return }
let plane = SCNPlane(width: CGFloat(planeAnchor.extent.x),
height: CGFloat(planeAnchor.extent.z))
...
}
指针非常感谢。
注意:
我目前正在考虑解决这两个问题的方式是引入一个 Bool,该按钮将通过按钮进行更改-这将决定 renderer(didAdd:在哪里工作或停止工作.(我不会在 renderer(didUpdate:上使用 Bool),因为它需要更新已检测到的飞机。另外,我将使用平截头体逻辑,以便在一处仅检测到一个平面。最后,我将跟踪飞机的更新数量,如果未达到阈值(例如 5),则将从场景中删除所有更新数量不能达到 5 的飞机。这可能会增加用户体验的稳定性,但是我强烈感觉这会增加用户想要的复杂性和约束。
我在想正确的方向吗?迫切需要一些更好的逻辑。
1 回答
更改
ARSession
的配置后,您需要再次调用run(_:options:)方法,以使其起作用。我不确定这是否是最佳做法,但您可以尝试执行以下操作来手动检查平面是否重叠:
将飞机投射到 xz-plane 上。由于 ARKit 仅支持水平表面检测,因此这应该相当容易。
使用 2D 碰撞检测方法检查飞机是否碰撞。
如果高于某个平面阈值的部分发生碰撞,请除去其中一个碰撞平面。您可能还需要检查两个平面在 3D 中是否足够靠近彼此。