【大咖专栏】Unity AR Foundation 平面检测实战

大咖介绍

AR是增强现实(AugmentedReality)的缩写,是一种将虚拟信息与真实世界巧妙融合的技术。首先通过摄像头捕获到真实世界的影像,辅以陀螺仪等传感器数据信息,通过软件算法为真实世界的影像构建虚拟空间的三维坐标系,在这个坐标系基础上添加三维模型等,从而达到使用虚拟信息与真实世界影像融合呈现的效果。

AR的优势

1.一套完成的VR(虚拟现实)设备价格不菲,而AR主流手机均可以支持。

2.得益于智能手机的普及,AR的受众人群更广泛。

3.AR应用场景广泛,包括:教育、医疗、购物、娱乐、传媒、旅游、军事等。

主流AR SDK对比

SDK

特点

平台

苹果ARKit

平面检测、运动跟踪、光线评估

iOS11,A9及以上处理器(iPhone6s及以后设备)

谷歌ARCore

平面检测、运动跟踪、光线评估

国内支持设备较少,并且需要安装Google Play和ARCore套件

Easy AR SDK

目前缺少平面检测和光线评估

Unity AR Foundation

底层技术基于ARKit和ARCore封装,对Unity开发非常友好

同ARKit和ARCore的设备

苹果的发布ARKit,提出的平面检测、运动跟踪、光线评估三大特色功能,把AR技术应用刷新到一个新的高度;谷歌紧随其后,发布了具有同样特色功能的ARCore。在需要平面检测,面积计算这样的AR应用场景,国内老牌的EasyAR已不能满足需求。Unity为了更好的支持游戏开发中应用AR技术,抽象了UnityAR Foundation框架,实现“构建一次,多平台部署”。无疑UnityAR Foundation已成为Unity中开发AR应用的首选框架。

Unity AR Foundation 架构

UnityAR Foundation需要Unity2019以上版本。ARFoundation 通过XR插件来支持不同的平台,不同平台对应的XR插件如下:

*Android 上需要ARCoreXR Plugin

*iOS 需要ARKitXR Plugin

*Magic Leap 需要MagicLeap XR Plugin

*HoloLens 需要WindowsXR Plugin

ARFoundation的框架图如下:

AR应用基于ARFoundation开发,ARFoundation屏蔽了不同平台ARSDK的API差异。

架构搭建AR Foundation项目

首先创建一个空的3D项目,然后点击菜单Window=> Package Manager, 在弹出的PackageManager窗口中搜索AR,在列表中选择ARKitXR Plugin进行安装。要使用ARFoundation,必须安装一个XRPlugin,考虑到iOS调试的便利性,我们选择iOS平台的ARKitXR Plugin进行初次学习。

ARKitXR Plugin的安装会自动触发ARFoundation和ARSubsystems包的安装,如下图所示:

开发包安装完毕,可以在层级管理器,资源管理器和项目设置中看到XR相关的信息,如下图所示:

现在我们可以通过层级管理器的右键菜单中的XR子菜单创建AR游戏对象了。

初始化场景

AR场景的摄像机由ARSession Origin管理,所以需要删除默认场景的MainCamera,通过层级管理器的XR菜单,创建如下图所示的游戏对象。

ARSession 和 ARSession Origin游戏对象自带了对应的脚本组件,并有默认的设置。需要注意的是,ARSession Origin下的ARCamera的ClearFlags不能用skybox,需要用SolidColor,如下图所示:

ARSession

ARSession游戏对象中的ARSession组件管理AR的开启和关闭,

ARSession组件可以挂在任意的GameObject上。禁用ARSession将停止AR系统的各种检测运算。ARSession提供了一个静态的协程方法CheckingAvailability,可以查询设备是否支持AR。下面的代码自定义一个脚本组件用来查询设备是否支持AR,注意Start函数的返回值修改为IEnumerator,以实现异步查询。

publicclass MyComponent : MonoBehaviour

[SerializeField] ARSessionm_Session;

IEnumerator Start() {

if ((ARSession.state ==ARSessionState.None) ||

(ARSession.state ==ARSessionState.CheckingAvailability))

{

yield returnARSession.CheckAvailability();

}

if (ARSession.state ==ARSessionState.Unsupported)

{

// Start somefallback experience for unsupported devices

}

else

{

// Start the ARsession

m_Session.enabled =true;

}

}

}

AR Session Origin

ARSessionOrigin游戏对象中的ARSessionOrigin组件处理AR世界坐标系到Unity坐标系的转换;ARPlaneManager处理平面检测;ARRaycastManager负责AR世界中的射线碰撞;

AR Camera

ARCamera处理摄像机的纹理捕获,镜头触发的画面移动由ARPose Driver完成。

平面检测

目前的默认设置已经具备平面检测能力,在这基础上我们需求进行一些交互,点击屏幕任意点,如果点在平面上,放置设定的3D模型到点的位置。

新建一个脚本组件,挂在ARSession Origin游戏对象上。其内容如下:

usingSystem.Collections.Generic;

usingUnityEngine;

usingUnityEngine.XR.ARFoundation;

usingUnityEngine.XR.ARSubsystems;

[RequireComponent(typeof(ARRaycastManager))]

publicclass PlaceOnPlane : MonoBehaviour

{

[SerializeField]

[Tooltip(“Instantiatesthis prefab on a plane at the touch location.”)]

GameObject m_PlacedPrefab;

///

/// The prefab toinstantiate on touch.

///

public GameObjectplacedPrefab

{

get { returnm_PlacedPrefab; }

set { m_PlacedPrefab =value; }

}

///

/// The object instantiatedas a result of a successful raycast intersection with a plane.

///

public GameObjectspawnedObject { get; private set; }

void Awake()

{

m_RaycastManager =GetComponent();

}

bool TryGetTouchPosition(outVector2 touchPosition)

{

#ifUNITY_EDITOR

if(Input.GetMouseButton(0))

{

var mousePosition =Input.mousePosition;

touchPosition = newVector2(mousePosition.x, mousePosition.y);

return true;

}

#else

if (Input.touchCount >0)

{

touchPosition =Input.GetTouch(0).position;

return true;

}

#endif

touchPosition = default;

return false;

}

void Update()

{

if(!TryGetTouchPosition(out Vector2 touchPosition))

return;

if(m_RaycastManager.Raycast(touchPosition, s_Hits,TrackableType.PlaneWithinPolygon))

{

// Raycast hits aresorted by distance, so the first one

// will be theclosest hit.

var hitPose =s_Hits[0].pose;

if (spawnedObject ==null)

{

spawnedObject =Instantiate(m_PlacedPrefab, hitPose.position, hitPose.rotation);

}

else

{

spawnedObject.transform.position= hitPose.position;

}

}

}

static Lists_Hits = new List();

ARRaycastManagerm_RaycastManager;

}

解析:

1.获取ARRaycastManager组件

2.获取触摸点,Raycast查询是否碰撞到AR平面。

3.如果碰撞到平面,创建模型实例,并设置位置到碰撞点。

发布测试

点击菜单File=> Build Setting, 切换Platform到iOS,点击build导出XCode工程,如下图所示:

打开Unity-iPhone.xcodeproj工程,在Xcode的账号设置中登录已注册iDP的账号,插入iPhone手机,并选择target为此手机,调整DeploymentTarget为11.0以上,如下图所示。

最后点击三角箭头启动程序,XCode自动编译并运行程序到手机上,最终效果如下图所示:

参考资料

    THE END
    喜欢就支持一下吧
    点赞8 分享
    评论 抢沙发
    头像
    欢迎您留下宝贵的见解!
    提交
    头像

    昵称

    取消
    昵称表情代码图片

      暂无评论内容