版权声明:Davidwang原创文章,严禁用于任何商业途径,授权后方可转载。
通过前面的学习我们知道,ARKit建立环境理解需要一定时间,这个时间长短取决于用户设备摄像头采集的图像质量(可信的特征点数量)和空间计算结果,在这个过程中,使用者可能并不知道ARKit正在进行这个工作,特别是对没有AR应用使用经验的人而言,会让他们感到困惑和迷茫。因此,为消除使用者的焦虑,同时更快的建立环境跟踪,应该给予使用者视觉或者文字引导,指导他们进行下一步操作。
ARKit提供了一个名为ARCoachingOverlayView的视图用于引导使用者进行操作,该视图共包括4种类型:指导使用者移动设备、指导使用者继续移动设备、指导使用者放慢设备移动速度、指导使用者如何重定位。在ARSession初始化时或者跟踪受限时,会显示如下图所示视图,引导用户移动设备检测水平平面或者垂直平面。
如果ARKit收集的环境信息还不足以检测平面,会显示如下图左图所示视图,引导用户通过继续移动设备以便ARKit收集更多环境信息,如果在这个过程中,用户移动设备速度过快,会造成采集的图像质量下降,这时会显示如下图右图所示视图,引导用户降低设备移动速度。
当ARKit收集到足够信息时,引导视图会自动消失,AR进入到正常跟踪状态。
重定位(relocalization)也是容易让使用者困惑的操作,不按照ARKit设定的方式进行特定环境扫描,重定位可能永远都无法成功。因此,引导使用者回到原工作环境中进行环境扫描非常重要,在进行重定位时,会显示如下图所示视图,引导使用者返回到ARSession中断前的环境中以便更好的进行重定位工作。
ARCoachingOverlayView提供一个标准的引导程序,在ARSession初始化或者跟踪受限时引导使用者进行下一步操作。在使用ARCoachingOverlayView时需要提供一个目标(goal),即在什么情况下引导结束,这个目标可以是检测到水平平面、垂直平面或者是跟踪建立。在ARKit中,这个目标由ARCoachingOverlayView.Goal枚举定义,该枚举各枚举项如下表所示。
枚举项 | 描述 |
---|---|
anyPlane | 任何平面,即包括垂直平面和水平平面 |
horizontalPlane | 水平平面 |
tracking | 建立世界跟踪 |
verticalPlane | 垂直平面 |
ARCoachingOverlayView的基本工作方式是,在达到开发人员指定的目标前,会显示引导视图指导使用者进行下一步操作,在达到指定目标后,则引导视图会自动消失。如果在AR应用运行过程中,由于某些原因导致跟踪受限或者需要重定位,也会显示引导视图。
在RealityKit中,使用ARCoachingOverlayView的基本步骤如下:
(1)设置ARCoachingOverlayView.goal为指定的目标;
(2)设置ARCoachingOverlayView.sesseion为当前使用的ARSession;
(3)根据需要使用代理方法。一般情况下我们会使用代理方法,因为我们不希望在引导视图未消失前出现UI元素或者虚拟元素,通过使用代理方法,在引导视图完成目标后才会在场景中加载虚拟元素。典型的使用ARCoachingOverlayView的方法如下代码清单所示。
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let config = ARWorldTrackingConfiguration()
config.planeDetection = .horizontal
arView.session.run(config, options:[ ])
arView.addCoaching()
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {
}
}
extension ARView: ARCoachingOverlayViewDelegate{
func addCoaching() {
let coachingOverlay = ARCoachingOverlayView()
coachingOverlay.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.addSubview(coachingOverlay)
coachingOverlay.goal = .horizontalPlane
coachingOverlay.session = self.session
coachingOverlay.delegate = self
}
public func coachingOverlayViewDidDeactivate(_ coachingOverlayView: ARCoachingOverlayView) {
self.placeBox()
}
@objc func placeBox(){
let boxMesh = MeshResource.generateBox(size: 0.15)
var boxMaterial = SimpleMaterial(color:.white,isMetallic: false)
let planeAnchor = AnchorEntity(plane:.horizontal)
do {
boxMaterial.baseColor = try .texture(.load(named: "Box_Texture.jpg"))
boxMaterial.tintColor = UIColor.white.withAlphaComponent(0.9999)
let boxEntity = ModelEntity(mesh:boxMesh,materials:[boxMaterial])
planeAnchor.addChild(boxEntity)
self.scene.addAnchor(planeAnchor)
} catch {
print("找不到文件")
}
}
}
上述代码使用ARCoachingOverlayView对使用者的操作进行引导,并使用了代理方法coachingOverlayViewDidDeactivate(),在达到目标后在场景中加载一个立方体。
使用ARCoachingOverlayView的代理方法,必须要遵循ARCoachingOverlayViewDelegate协议,该协议定义了3个可选(optional)方法,如下表所示。
方法 | 描述 |
---|---|
coachingOverlayViewWillActivate(ARCoachingOverlayView) | 在ARCoachingOverlayView激活时调用 |
coachingOverlayViewDidDeactivate(ARCoachingOverlayView) | 在ARCoachingOverlayView完成目标消失时调用 |
coachingOverlayViewDidRequestSessionReset(ARCoachingOverlayView) | 在重定位时,当用户点击“Start Over”按钮要求重置ARSession时调用 |
ARCoachingOverlayView有一个布尔类型的activatesAutomatically属性(该属性默认为true),用于指示ARCoachingOverlayView是否自动激活(如在跟踪受限时或者需要重定位时),默认情况下是会自动激活,在激活前,我们可以通过coachingOverlayViewWillActivate(_:)代理方法执行一些必要操作,如隐藏UI、暂停AR进程等等。
在允许重定位时,ARKit会在ARSession中断后尝试重新建立虚实联系,在这种情况下, ARCoachingOverlayView也会激活,并且会出现一个“Start Over”按钮,该按钮允许使用者直接重置ARSession而不是重定位。如果使用者点击“Start Over”按钮,coachingOverlayViewDidRequestSessionReset( ) 代理方法就会执行,因此可以在该方法里执行一些ARSession重置的操作,典型的代码如下代码清单所示。
func coachingOverlayViewDidRequestSessionReset(_ coachingOverlayView: ARCoachingOverlayView) {
// 重置session.
let configuration = ARWorldTrackingConfiguration()
configuration.planeDetection = [.horizontal, .vertical]
session.run(configuration, options: [.resetTracking])
// 其他操作...
}
如果我们没有执行该方法,那么ARKit会自动执行ARSession重置,并清除所有ARAnchor。