Update:从 iOS 11.3(又名“ARKit 1.5”)开始,is添加之间的区别ARAnchor
到会话(然后通过将 SceneKit 内容与其关联ARSCNViewDelegate
回调)并将内容放置在 SceneKit 空间中。
当您向会话添加锚点时,您是在告诉 ARKit 世界空间中的某个点与您的应用程序相关。然后,ARKit 可以做一些额外的工作,以确保其世界坐标空间与现实世界准确对齐,至少在该点附近。
因此,如果您试图使虚拟内容看起来“附加”到某些现实世界的兴趣点,例如将物体放在桌子或墙上,那么您应该会看到由于世界跟踪不准确而导致的“漂移”较少,如果您给出该对象是一个锚点,而不是将其放置在 SceneKit 空间中。如果该对象从一个静态位置移动到另一个静态位置,您将需要删除原始锚点并随后在新位置添加一个锚点。
此外,在 iOS 11.3 中,您可以opt in https://developer.apple.com/documentation/arkit/arsessionobserver/2941046-sessionshouldattemptrelocalizati到“重新定位”,这是一个帮助 ARKit 在会话中断(通过电话、切换应用程序等)后恢复会话的过程。该会话在尝试找出如何将您之前所在的位置映射到现在所在的位置时仍然有效,这可能会导致一旦重新定位成功,锚点的世界空间位置就会发生变化。
(另一方面,如果你只是制作漂浮在空中的太空入侵者,那么完美匹配的世界空间并不那么重要,因此你不会真正看到基于锚点和非基于锚点之间的太大区别定位。)
请参阅 Apple 中有关“使用锚点提高虚拟对象周围的跟踪质量”的部分处理增强现实中的 3D 交互和 UI 控件 https://developer.apple.com/documentation/arkit/handling_3d_interaction_and_ui_controls_in_augmented_reality文章/示例代码。
这个答案的其余部分在历史上仍然与 iOS 11.0-11.2.5 相关,并解释了一些上下文,所以我将其留在下面......
首先考虑使用ARAnchor
without场景套件。
如果您正在使用ARSKView
,您需要一种方法来参考 3D(真实世界)空间中的位置/方向,因为 SpriteKit 不是 3D。你需要ARAnchor
跟踪 3D 中的位置,以便将它们映射到 2D 中。
如果您使用 Metal(或 GL,出于某种奇怪的原因)构建自己的引擎...这不是 3D 场景描述 API — 它是 GPU 编程 API — 所以它实际上没有世界空间的概念。您可以使用ARAnchor
作为 ARKit 的世界空间概念和您构建的任何内容之间的桥梁。
所以在某些情况下你需要ARAnchor
因为这是引用 3D 位置的唯一合理方式。 (当然,如果你使用平面检测,你需要ARPlaneAnchor
因为 ARKit 实际上会相对于场景空间移动那些,因为它改进了对飞机位置的估计。)
With ARSCNView
,SceneKit 已经有了一个 3D 世界坐标空间,ARKit 完成了使该空间与 ARKit 映射的真实世界空间相匹配的所有工作。所以,给定一个float4x4
描述世界空间中的位置(和方向等)的变换,您可以:
- 创建一个
ARAnchor
,将其添加到会话中,并响应ARSCNViewDelegate
回调为每个锚点提供 SceneKit 内容,ARKit 将为您添加到场景中并在场景中定位。
- 创建一个
SCNNode
,设置其simdTransform
,并将其添加为场景的子级rootNode
.
只要你有跑步的习惯ARSession
,这两种方法之间没有区别——它们是表达同一件事的等效方式。因此,如果您喜欢以 SceneKit 方式做事,那没有什么问题。 (你甚至可以使用SCNVector3
and SCNMatrix4
如果需要,可以使用 SIMD 类型来代替 SIMD 类型,但如果您还从 ARKit API 获取 SIMD 类型,则必须来回转换。)
这些方法的一个不同之处是会话重置时。如果世界跟踪失败,您将恢复中断的会话,和/或
当您重新开始会话时,“世界空间”可能不再像您在场景中放置内容时那样与现实世界对齐。
在这种情况下,您可以让 ARKit 从会话中删除锚点 - 请参阅run(_:options:) https://developer.apple.com/documentation/arkit/arsession/2875735-run方法和ARSession.RunOptions https://developer.apple.com/documentation/arkit/arsession.runoptions。 (是的,所有这些,因为此时您不能相信它们中的任何一个都有效。)如果您使用锚点和委托回调将内容放置在场景中,ARKit 将删除所有内容。 (您会收到正在删除的委托回调。)如果您使用 SceneKit API 放置内容,它会保留在场景中(但很可能位于错误的位置)。
因此,使用哪个取决于您想要如何处理会话失败和中断(除此之外没有真正的区别)。