在上一篇博客中,我们了解了 2D 图像跟踪,让我们看看 Unity 如何更轻松地检测现实世界中的平面,并使用该平面放置或生成任何对象。
最著名的生活场景是宜家。你可能知道宜家如何通过移动应用程序将数字家具放置在我们的客厅中。
NSDT工具推荐 : Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割
我们将尝试构建类似的东西,源码可以从这里下载。
1、Unity 的设置
在 Unity 中,创建一个项目并选择一个空的 3D 模板。
首先,我们需要配置 Player Build Settings,将 Build 平台切换到你最喜欢的设备,然后从 Package Manager 添加包 AR Foundation 和设备特定的插件包,如 ARCore 或 ARKit,在本例中,我使用了 iOS 设备,因此下载了 ARKit XR 插件。你可以从此处查看配置步骤。
接下来,删除 3D 模板添加的 MainCamera 对象,并将 AR 体验的必需对象添加到你的场景、AR 会话和 AR 会话原点。
在 AR Session Origin 内部,有一个 AR Camera,将其标记为 MainCamera。
到目前为止,我们已经完成了 Unity 的 AR 开发设置。
接下来,我们必须为平面检测和将物体放置在检测到的平面上设置一些东西。因此,让我们首先为平面检测进行非常基本的设置,然后我们可以在稍后将物体放置在平面上时进行即兴发挥。
2、平面检测
为此,我们需要将 AR Plane Manager(一个预定义的脚本)作为组件添加到 AR Session Origin 中。
它有 3 个字段,Script 包含它自己的脚本,Plane Prefab,这是我们需要添加平面特征的游戏对象的地方,然后每当 AR 摄像头检测到现实世界中的表面或平面时,该 Prefab 就会绘制在这些表面上。检测模式,默认为 Everything,意味着管理器将检测每种类型的平面,无论是垂直还是水平,可以根据我们的要求进行设置。比如只有垂直或只有水平。
添加 AR Plane Manager 后,我们需要将一些游戏对象分配给 Plane Prefab 字段。
我们有 3 种方法可以做到这一点,我们可以使用Unity Asset Store中提供的各种 3D 平面网格,或者我们可以使用 AR Foundation 提供的默认 AR 平面,或者我们可以构建自定义平面并添加平面组件,如网格过滤器、网格渲染器、线渲染器等。
为此,我选择默认 AR 平面,可以在 XR 子菜单中找到。
就这样,我们完成了,现在将该 AR 平面从层次结构拖到 Assets 的文件夹结构中,现在它变成了预制件,并将其从层次结构中移除。
最后,将该预制件拖到 AR Session Origin 中 AR Plane Manager 的 Plane Prefab 字段。
在这里,我们完成了非常基本的平面检测设置。在设备上构建并运行它以查看其工作原理。
如果一切正常,那么让我们继续放置对象。
3、放置对象
此过程需要对光线投射有所了解。
光线投射(raycasting):投射光线以帮助估计 AR 物体应放置在何处,以便以可信的方式出现在现实世界表面;用于命中测试。
那么什么是命中测试(hit-testing)呢?命中测试可让你为虚拟物体建立姿势,是 AR 用户流程中继特征跟踪和平面查找之后的下一步。
在我们的例子中,我们找到了平面,现在我们必须执行光线投射来放置物体。
为了实现这一点,我们需要在此处编写一些代码。你可以从 Github 下载。
在 Assets 文件夹中 > 右键单击 > 创建 C# 脚本 > 命名,例如 PlaceObjectScript,双击并在编辑器中打开
导入 XR 库:
using UnityEngine.XR.ARSubsystems;
using UnityEngine.XR.ARFoundation;
我们需要的最重要的组件是 ARRaycastManager
,所以我们会让班级知道我们需要这个家伙,这是强制性的。
我们知道进一步声明脚本中需要的一些变量。
public GameObject gameObjectToInstantiate;
private GameObject spawnedGameObject;
private ARRaycastManager _aRRaycastManager;
static List<ARRaycastHit> hits = new List<ARRaycastHit>();
gameObjectToInstantiate
,在我们的例子中,我们将分配我们的 3D 汽车预制件。spawnedGameObject
,当用户点击屏幕时,gameObject 将在此处分配。_aRRaycastManager
,通过此变量,我们可以执行射线投射,然后将对象放置在用户点击的位置。hits
,获取 RayCast 命中列表。
此后,我们需要在 Awake()
方法中初始化 _aRRaycastManager
。删除 Start()
方法,我们不会将其用于我们的应用。
接下来,我们需要用户在屏幕上点击或触摸的位置,为此创建一个新方法,如下所示,
bool TryGetTouchPosition(out Vector2 touchPosition)
{
if(Input.touchCount > 0)
{
touchPosition = Input.GetTouch(0).position;
return true;
}
touchPosition = default;
return false;
}
现在我们需要实例化一个 gameObject,当我们从上述方法获得屏幕上点击区域的位置和真值时,它会生成 GameObject。
在 Update()
中,写入以下几行:
脚本编写完毕。现在回到 Unity。
只需将创建的脚本拖到 AR Session Origin Inspector 部分,必须将其添加为组件。
AR Raycast Manager 会自动添加到组件中,这是因为我们在顶部将 PlaceObjectScript 指定为 RequireComponent()
。保持原样即可。
最后,将你的预制件拖到 Game Object To Instantiate 字段:
我们还可以在 AR 平面管理器中将检测模式更改为水平,以避免检测垂直平面。
瞧,我们成功了。