Follow best practices for visual feedback, gesture interactions, and realistic rendering in AR experiences.
融合视觉反馈,手势交互和逼真渲染的最佳AR体验。
Overview
Augmented reality (AR) offers new ways for users to interact with real and virtual 3D content in your app. However, many fundamental principles of human interface design are still valid. Convincing AR illusions also require careful attention to 3D asset design and rendering. The iOS Human Interface Guidelines include advice on human interface principles for AR. This project shows ways to apply those guidelines and easily create immersive, intuitive AR experiences.
This sample app provides a simple AR experience allowing a user to place one or more realistic virtual objects in their real-world environment, then arrange those objects using intuitive gestures. The app offers user interface cues to help the user understand the state of the AR experience and their options for interaction.
The sections below correspond to sections in iOS Human Interface Guidelines > Augmented Reality, and provide details on how this sample app implements those guidelines. For more detailed reasoning on each section, see the corresponding content in the iOS Human Interface Guidelines.
概述
增强现实(AR)为用户提供了与应用中的真实和虚拟3D内容交互的新方法。 但是,人机界面设计的许多基本原则仍然有效。 令人信服的AR场景也需要仔细关注3D Asset设计和渲染。 iOS人机界面指南包含有关AR人机界面原则的建议。 该项目展示了如何应用这些指导方针并轻松创建身临其境的直观AR体验。
此示例应用程序提供了一种简单的AR体验,允许用户将一个或多个真实的虚拟对象置于其真实世界的环境中,然后使用直观的手势排列这些对象。 该应用程序提供用户界面提示,以帮助用户了解AR体验的状态及其交互选项。
以下各节对应于iOS人机界面指南>增强现实中的各个部分,并提供有关此示例应用程序如何实现这些指南的详细信息。 有关每个部分的更详细推理,请参阅iOS人机界面指南中的相应内容。
Placing Virtual Objects
Help people understand when to locate a surface and place an object. The FocusSquareclass draws a square outline in the AR view, giving the user hints about the status of ARKit world tracking.
放置虚拟物品
帮助人们了解何时找到表面并放置物体。 FocusSquareclass在AR视图中绘制方形轮廓,为用户提供有关ARKit世界跟踪状态的提示。
The square changes size and orientation to reflect estimated scene depth, and switches between open and closed states with a prominent animation to indicate whether ARKit has detected a plane suitable for placing an object. After the user places a virtual object, the focus square disappears, remaining hidden until the user points the camera at another surface.
Respond appropriately when the user places an object. When the user chooses a virtual object to place, the sample app’s setPosition(_:relativeTo:smoothMovement)method uses the FocusSquare object’s simple heuristics to place the object at a roughly realistic position in the middle of the screen, even if ARKit hasn’t yet detected a plane at that location.
正方形改变大小和方向以反映估计的场景深度,并通过突出的动画在打开和关闭状态之间切换,以指示ARKit是否检测到适合放置对象的平面。 用户放置虚拟物体后,焦点正方形消失,保持隐藏状态,直到用户将相机指向另一个表面。
当用户放置对象时适当地作出响应。 当用户选择要放置的虚拟对象时,即使ARKit在那个位置没有检测到一个平面,示例应用程序的setPosition(_:relativeTo:smoothMovement)方法也会使用FocusSquare对象的简单启发式方法将对象置于屏幕中间的大致实际位置。
This position might not be an accurate estimate of the real-world surface the user wants to place the virtual object on, but it’s close enough to get the object onscreen quickly.
Over time, ARKit detects planes and refines its estimates of their position, calling the renderer:didAddNode:forAnchor: and renderer:didUpdateNode:forAnchor:delegate methods to report results. In those methods, the sample app calls its adjustOntoPlaneAnchor(_:using:) method to determine whether a previously placed virtual object is close to a detected plane. If so, that method uses a subtle animation to move the virtual object onto the plane, so that the object appears to be at the user’s chosen position while benefiting from ARKit’s refined estimate of the real-world surface at that position:
这个位置可能不是用户想要放置虚拟物体的真实世界表面的准确估计,但它足够接近以快速获取屏幕上的对象。
随着时间的推移,ARKit会检测平面并提高其位置估计值,并调用渲染器:didAddNode:forAnchor:和renderer:didUpdateNode:forAnchor:委托方法报告结果。 在这些方法中,示例应用程序调用其adjustOntoPlaneAnchor(_:using :)方法来确定先前放置的虚拟对象是否靠近检测到的平面。 如果是这样,该方法使用微妙的动画将虚拟物体移动到平面上,以便物体看起来在用户选择的位置,同时受益于ARKit在该位置对现实世界表面的精确估计:
Use anchors to improve tracking quality around virtual objects. Whenever you place a virtual object, always add an ARAnchor representing its position and orientation to the ARSession. After moving a virtual object, remove the anchor at the old position and create a new anchor at the new position. Adding an anchor tells ARKit that a position is important, improving world tracking quality in that area and helping virtual objects appear to stay in place relative to real-world surfaces. (See the sample code’s addOrUpdateAnchor() method.)
使用锚点来提高虚拟物体周围的跟踪质量。 每当你放置一个虚拟对象时,总是添加一个ARAnchor来表示它的位置和方向到ARSession。 移动虚拟对象后,移除旧位置的锚点并在新位置创建一个新锚点。 添加一个锚点告诉ARKit一个位置是重要的,提高了该区域的世界跟踪质量,并帮助虚拟对象看起来相对于真实世界的表面保持原位。 (请参阅示例代码的addOrUpdateAnchor()方法。)
User Interaction with Virtual Objects
Allow people to directly interact with virtual objects using standard, familiar gestures. The sample app uses one-finger tap, one- and two-finger pan, and two-finger rotation gesture recognizers to let the user position and orient virtual objects. The sample code’s VirtualObjectInteraction class manages these gestures.
In general, keep interactions simple. When dragging a virtual object (see the translate(_:basedOn:infinitePlane:) method), the sample app restricts the object’s movement to the two-dimensional plane it’s placed on. Similarly, because a virtual object rests on a horizontal plane, rotation gestures (see the didRotate(_:) method) spin the object around its vertical axis only, so that the object remains on the plane.
Respond to gestures within reasonable proximity of interactive virtual objects. The sample code’s objectInteracting(with:in:) method performs hit tests using the touch locations provided by gesture recognizers. By hit testing against the bounding boxes of the virtual objects, the method makes it more likely that a user touch will affect the object even if the touch location isn’t on a point where the object has visible content. By performing multiple hit tests for multitouch gestures, the method makes it more likely that the user touch affects the intended object:
用户与虚拟对象的交互
允许人们使用标准,熟悉的手势直接与虚拟对象交互。示例应用程序使用单指轻拍,单指和双指锅,以及双指旋转手势识别器来让用户定位和定位虚拟对象。示例代码的VirtualObjectInteraction类管理这些手势。
一般而言,保持交互简单。拖动虚拟对象时(请参阅translate(_:basedOn:infinitePlane :)方法),示例应用程序将对象的移动限制为其放置的二维平面。同样,由于虚拟物体停留在水平面上,旋转手势(请参阅didRotate(_ :)方法)仅将物体围绕其垂直轴旋转,以使物体保持在平面上。
在合理接近交互式虚拟对象的情况下对手势做出响应。示例代码的objectInteracting(with:in :)方法使用手势识别器提供的触摸位置执行命中测试。通过针对虚拟对象的边界框进行命中测试,该方法使得即使触摸位置不在对象具有可见内容的点上,用户触摸也更有可能影响对象。通过对多点触控手势执行多个命中测试,该方法使得用户触摸更有可能影响预期的对象:
Consider whether user-initiated object scaling is necessary. This AR experience places realistic virtual objects that might naturally appear in the user’s environment, so preserving the intrinsic size of the objects aids realism. Therefore, the sample app doesn’t add gestures or other UI to enable object scaling. Additionally, by not including a scale gesture, the sample app prevents a user from becoming confused about whether a gesture resizes an object or changes the object’s distance from the camera. (If you choose to enable object scaling in your app, use a pinch gesture recognizer.)
Be wary of potentially conflicting gestures. The sample code’s ThresholdPanGestureclass is a UIPanGestureRecognizer subclass that provides a way to delay the gesture recognizer’s effect until after the gesture in progress passes a specified movement threshold. The sample code’s touchesMoved(with:) method uses this class to let the user smoothly transition between dragging an object and rotating it during a single two-finger gesture:
考虑用户启动的对象缩放是否必要。这种AR体验放置了可能自然出现在用户环境中的逼真的虚拟对象,因此保留对象的固有尺寸有助于保持真实感。因此,示例应用程序不会添加手势或其他UI来启用对象缩放。此外,通过不包含比例手势,示例应用程序可防止用户对手势调整对象大小或改变对象与相机的距离感到困惑。 (如果您选择在应用中启用对象缩放,请使用捏手势识别器。)
警惕潜在的冲突手势。示例代码的ThresholdPanGestureclass是一个UIPanGestureRecognizer子类,它提供了一种方法来延迟手势识别器的效果,直到手势正在进行超过指定的移动阈值。示例代码的touchesMoved(with :)方法使用此类来让用户在单个双指手势中拖动对象并旋转它之间平滑过渡:
Make sure virtual object movements are smooth. The sample code’s setPosition(_:relativeTo:smoothMovement) method interpolates between the touch gesture locations that result in dragging an object and a history of that object’s recent positions. By averaging recent positions based on distance to the camera, this method produces smooth dragging movement without causing the dragged object to lag behind the user’s gesture:
确保虚拟物体移动平稳。 示例代码的setPosition(_:relativeTo:smoothMovement)方法在导致拖动对象的触摸手势位置和该对象最近位置的历史记录之间插值。 通过基于距相机的距离平均最近的位置,该方法产生平滑的拖动运动,而不会导致被拖动的物体滞后于用户的手势:
Explore even more engaging methods of interaction. In an AR experience, a pan gesture—that is, moving one’s finger across the device’s screen—isn’t the only natural way to drag virtual content to a new position. A user might also intuitively try holding a finger still against the screen while moving the device, effectively dragging the touch point across the AR scene.
The sample app supports this kind of gesture by calling its updateObjectToCurrentTrackingPosition() method continually while a drag gesture is in progress, even if the gesture’s touch location hasn’t changed. If the device moves during a drag, that method calculates the new world position corresponding to the touch location and moves the virtual object accordingly.
探索更吸引人的互动方式。 在AR体验中,平移手势 - 即将手指移动到设备的屏幕上 - 并不是将虚拟内容拖到新位置的唯一自然方式。 用户也可以在移动设备时直观地尝试将手指保持在屏幕上,有效地将触摸点拖过AR场景。
即使手势的触摸位置没有改变,示例应用也会在拖动手势正在进行时通过不断调用其updateObjectToCurrentTrackingPosition()方法来支持这种手势。 如果设备在拖动过程中移动,该方法将计算与触摸位置相对应的新世界位置并相应地移动虚拟对象。
Entering Augmented Reality
Indicate when initialization is occurring and involve the user. The sample app shows textual hints about the state of the AR session and instructions for interacting with the AR experience using a floating text view. The sample code’s StatusViewController class manages this view, showing transient instructions that fade away after allowing the user time to read them, or important status messages that remain visible until the user corrects a problem.
输入增强现实
指示何时进行初始化并涉及用户。 示例应用程序显示有关AR Session状态的文本提示以及使用浮动文本视图与AR体验交互的说明。 示例代码的StatusViewController类管理此视图,显示在允许用户读取它们后即刻消失的瞬态指令,或直到用户纠正问题时才显示的重要状态消息。
Handling Problems
Allow people to reset the experience if it doesn’t meet their expectations. The sample app has a Reset button that’s always visible in the upper-right corner of the UI, allowing a user to restart the AR experience regardless of its current state. See the restartExperience()method in the sample code.
Offer AR features only on capable devices. The sample app requires ARKit for its core functionality, so it defines the arkit key in the UIRequiredDeviceCapabilities section of its Info.plist file. When deploying the built project, this key prevents installation of the app on devices that don’t support ARKit.
If your app instead uses AR as a secondary feature, use the isSupported method to determine whether to hide features that require ARKit.
处理问题
如果它不符合他们的期望,允许人们重置体验。 示例应用程序具有重置按钮,该按钮始终在用户界面的右上角可见,允许用户重新启动AR体验,而不管其当前状态如何。 请参阅示例代码中的restartExperience()方法。
仅在有能力的设备上提供AR功能。 示例应用程序需要ARKit的核心功能,因此它在其Info.plist文件的UIRequiredDeviceCapabilities部分中定义了arkit密钥。 部署构建的项目时,此键可防止在不支持ARKit的设备上安装应用程序。
如果您的应用改为使用AR作为辅助功能,请使用isSupported方法确定是否隐藏需要ARKit的功能。