介绍
AR 的功能其实是个大手机系统厂商和眼镜设备厂商开发的功能,并不是Unity的功能,毕竟Unity没有自己的手机设备!比如谷歌公司的安卓开发了ARcore,让所有安卓8.0版本以上的用户能够在手机上体验AR功能!苹果推出了ARKit,让苹果用户能够在苹果手机上体验AR,还有一些眼镜厂商开发了相关的底层AR功能,比如微软Hololens2 苹果的VisionPro,magic leap!都在底层支持了AR!具体如下:
ARCore 是由 Google 开发的,用于 Android 设备的增强现实平台。它允许开发者为 Android 设备创建增强现实应用。根据搜索结果678,ARCore 利用手机的摄像头和传感器来感知环境,并通过运动跟踪、环境理解、光照估计等技术,将虚拟内容与现实世界相结合。此外,ARCore 还支持增强图像(Augmented Images)、云锚点(Cloud Anchors)等功能,为用户带来更加丰富的AR体验。
ARKit 是 Apple 推出的增强现实开发平台,专门用于 iOS 设备。根据搜索结果123,ARKit 经过多次迭代,提供了从简单的平面跟踪到人体追踪等丰富的功能。ARKit 2 引入了共享体验、持久增强现实体验、物体检测和图像追踪等功能,使得开发者能够创建更加生动和逼真的AR体验。
除了手机系统厂商,一些眼镜设备厂商也在开发底层的AR功能。例如,微软的 HoloLens 2 是一款混合现实(MR)设备,它通过先进的传感器和摄像头,为用户提供沉浸式的AR体验。而苹果的 VisionPro(如果指的是 Apple 的智能眼镜项目,目前尚未发布具体产品,因此可能是指未来或概念性产品)和 magic leap(一家AR眼镜公司,虽然与 Apple 无关,但也是AR领域的知名厂商)也在进行相关技术的研发。
还有华为手机的华为AR Engine
但是,我们开发AR不能学习那么多平台的底层开发工具去开发不同的平台!太累了!Unity作为带头大哥,干脆一口气在他们的底层基础上开发了一个让用户只需要在Unity写C# 就可以发布AR产品,走到哪里调用哪里的AR底层实现AR功能!自由穿梭在ARCore、ARKit、VisionPro、HoloLens 2、 magic leap之间,到哪里就用哪里的底层AR功能!这个面向用户的开发包就叫:
ARFoundation!
ARFoundation集成了大部分识别功能,但是有些功能不一定支持你的手机。
AR Foundation 是 Unity 提供的一个用于构建增强现实(AR)应用的跨平台框架。它包括了一系列的识别模块,这些模块使得开发者能够识别和追踪现实世界中的不同特征。以下是 AR Foundation 中一些常见的识别模块:
1. 平面检测(Plane Detection):
- 用于识别和追踪水平或垂直表面,如地板、桌面、墙壁等。这些平面可以作为放置虚拟物体的稳定基础。2. 图像识别(Image Recognition):
- 允许开发者指定特定的图像,AR 系统能够识别这些图像并在现实世界中追踪它们的位置和方向。3. 物体识别(Object Recognition):
- 可以识别和追踪三维物体,使得虚拟内容能够与现实世界的物体进行交互。4. 人脸追踪(Face Tracking)**:
-用于检测和追踪人脸的特征,如眼睛、嘴巴等,常用于面部滤镜或面部表情驱动的虚拟角色。5. 人体追踪(Body Tracking):
- 识别和追踪人体的姿态和运动,可以用于创建更加自然和互动的 AR 体验。6. 环境探测(Environment Probes):
- 用于收集环境的光照信息,以便于更真实地渲染虚拟物体,使其与现实世界的光照条件相匹配。7. 边界检测(Boundary Detection):
- 识别用户周围的空间边界,防止虚拟物体超出用户的视野范围或与现实世界的物体发生不必要的遮挡。8. 点云(Point Cloud):
- 通过摄像头捕获的图像,AR 系统能够生成现实世界环境的点云数据,这些数据可以用来创建环境的三维表示。9. 光照估计(Light Estimation):
- 估计现实世界中的光照条件,帮助虚拟物体的渲染更加真实。10. 场景描述(Scene Description):
- 提供对当前环境的描述,包括物体、纹理、光照等信息,有助于构建更加丰富的 AR 场景。这些模块共同构成了 AR Foundation 的核心功能,使得开发者能够创建出能够与现实世界互动的丰富和沉浸式的 AR 体验。通过这些识别模块,AR 应用能够更好地理解和融入用户的现实环境。
今天学第一课,Unity开发ARFoundation相关应用搭建ARFoundation框架!
1.首先安装ARFoundation包
包管理器,选择UnityRegistry-找到ARfoundation,下载导入!
2.然后设置XR
选择你未来发布到的使用设备平台,勾选对应底层插件!
我这里选择了安卓!
如果是URP渲染模式的场景,普通渲染模式没有下面的画面,还需要在Graphics选择XR渲染管线设置!
3.基础AR场景框架搭建
3.1 创建老祖宗ARsession
右键创建XR-选择ARsession(每个工程都需要有它,他就像总管理,负责通信于不同设备底层AR框架,以及AR生命周期、管理调用底层设备的不同追踪功能)
创建完毕后就静静的放在这里。
3.2 创建XR Origin(老版本叫ARsession Origin)
哇!这个是虚拟世界通往现实世界的桥梁,奈何桥!负责把Unity中的虚拟物体坐标转换为现实世界的坐标!也是UnityAR摄像机所被管理的地方!
想象一下,AR Session Origin 就像是一位舞者在舞台上的位置和动作的记录员。在增强现实中,我们的虚拟世界(就像舞者)需要在现实世界(舞台)中找到自己的位置并进行表演。AR Session Origin 就是确保虚拟舞者能够准确地在现实世界的舞台上找到自己的位置,并根据舞台的大小和布局调整自己的动作。
空间转换:就像舞者需要知道自己在舞台上的哪个位置,AR Session Origin 帮助虚拟物体理解自己在现实世界中的具体位置。它是一个参考点,告诉虚拟物体:“这是你的起始点,现在根据这个点来定位自己。”
管理虚拟相机:想象一下,AR Session Origin 是一位导演,它指挥着虚拟相机,告诉它应该在哪里放置,以便捕捉到最佳的视角和画面。这样,无论舞者在舞台上如何移动,相机都能跟随并记录下每一个动作。
应用变换和缩放:如果舞台突然变大或变小,舞者需要调整自己的动作和表演范围。AR Session Origin 通过缩放和变换来告诉虚拟物体,现实世界的舞台现在是怎样的,你需要如何调整自己以适应这个新的舞台。
维护跟踪数据:AR Session Origin 就像是一位记录员,它记录下舞者在舞台上的每一个动作和位置变化,确保虚拟物体能够准确地反映现实世界中的动态。
定义原点位置:在表演开始之前,舞者需要知道舞台的中心点在哪里,这样他们才能围绕这个点进行表演。AR Session Origin 就是这个中心点,它定义了虚拟物体在现实世界中的起始位置。
3.3 创建一个虚拟的美术模板来标记识别到的地面!AR Default Plane
继续右键XR-AR Default Plane
这其实就是个美术资源,识别到地面以后,我们用一个网格标记出来,让用户知道地面被识别的!
因此我们创建它是需要把它做成预制体将来赋值给专门识别地面的脚本!
拖到Asset仓库生产预制体,然后场景的AR Default Plane 就可以删除了!
3.4 添加一个用于识别平面的功能性脚本组件!给XR Origin(老版本叫ARsession Origin)
记住:组件即功能!孙悟空72变就像他有了72个不同组件!这是UNITY的软件逻辑!
给XR Origin(老版本叫ARsession Origin)右边添加组件,搜AR Plane Manager! 添加完毕!
AR Plane Manager就是一个组件,他是AR Foundation 功能中的其中一个常用的可跟踪对象管理器,类似的还有人脸跟踪管理器、人体跟踪管理器组件等。
虽然平面可以被识别,但是我们需要一个美术效果标记被识别的屏幕!平面可跟踪对象管理器不负责渲染美术效果,但是它提供了一Prefab变量入口,你可以把你做好的美术效果填到这里!如果不填,他会创建一个空对象。
他只有一个变量,就是需要一个漂亮的3D美术图标记将来我识别到的地面!就是3.3 我们设置好的!
3.5 到这里框架搭建完毕! 到这里框架搭建完毕!发布出去就可以识别地面了!
4 自己写个脚本!实现在地面上点击克隆一个3D立方体!
这个脚本写好之后 挂在XROrigin上
4.1脚本AppController 脚本业务逻辑
业务逻辑
AppController`脚本旨在实现一个基本的 AR 应用程序功能:用户通过触摸屏幕选择位置,然后在这个位置上克隆并放置一个预制的游戏对象。这个功能在 AR 应用程序中很常见,例如在游戏、教育或设计应用程序中,用户可以在现实世界的位置上放置虚拟物体。
4.2 AppController 脚本代码:
using JetBrains.Annotations; using System.Collections; using System.Collections.Generic; using Unity.VisualScripting; using UnityEngine; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; [RequireComponent(typeof(ARRaycastManager))]//当你在脚本中使用 [RequireComponent] 属性时,Unity编辑器会在编辑模式下自动检查并确保该组件存在于游戏对象上。如果该组件不存在,Unity会提示你添加它。这有助于避免在运行时出现错误,因为如果脚本依赖于某个组件,而该组件没有出现在游戏对象上,那么在游戏运行时尝试访问该组件的任何尝试都会导致错误或异常。 public class AppController : MonoBehaviour { // 主要实现了用户点击位置,克隆游戏物体 //1.获取用户点击位置,发射射线,碰撞到平面,返回坐标,克隆物体在此 public GameObject OnePrefab;//将来被克隆放置的预制体 static List<ARRaycastHit> ManyHits;//存储很多个 撞击物体后的相关信息 private ARRaycastManager OneRaycastManager;//存储射线发射器组件 private GameObject TempObj = null;//用户点击地面后!存储克隆在地面上被放置的物体 void Start() { ManyHits = new List<ARRaycastHit>();//声明投射 OneRaycastManager = this.gameObject.GetComponent<ARRaycastManager>();//获取脚本所在物体的ARRaycastManager组件 } // 获取用户点击行为, void Update() { if (Input.touchCount == 0)//如果点击0 { return; } // 获取第一个触摸点的信息 Touch OneTouch = Input.GetTouch(0);//获取第一个触摸点 //开始声明射线然后投射出去,物理引擎是用physic.Raycast。这里用ARRaycastManager投射,就像人扔东西一样 //一边发射一边判断是否射中平面 if (OneRaycastManager.Raycast(OneTouch.position, ManyHits, TrackableType.PlaneWithinPolygon | TrackableType.PlaneWithinBounds)) { //AR射线管理器组件向触摸点的位置发射一根射线并且击中平面,射线追踪类型为虚拟多边形平面目标类型 Debug.Log("射线发射成功, /射线击中了边界内的平面开始处理命中结果"); Pose FirstHitPose = ManyHits[0].pose;//存储第一个击中目标信息,包括对方名字、交叉点坐标 //开始克隆 if (TempObj == null) { TempObj = GameObject.Instantiate(OnePrefab, FirstHitPose.position, FirstHitPose.rotation); } else { TempObj.transform.position = FirstHitPose.position; } //为了防止重复点击,重复克隆,可以判断TempObj 是不是空 } } }
第二个课堂版本
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR; using UnityEngine.XR.ARFoundation; using UnityEngine.XR.ARSubsystems; public class ARPlaneCloneObj : MonoBehaviour { // 发射 public ARRaycastManager oneRaymanager;//记得外部赋值 public List<ARRaycastHit> MyRaycastHited;//记得外部赋值 public GameObject muban;//记得外部赋值 public Transform oneFather; //记得外部赋值 void Update() { //1.创建一根射线 if (Input.touchCount>=0) { Debug.Log("用户开始触摸了"); Touch oneTouchPoint = Input.GetTouch(0); GameObject Temp=null; // Ray oneshotRay = Camera.main.ScreenPointToRay(new Vector3(oneTouchPoint.position.x, oneTouchPoint.position.y,1)); if (oneRaymanager.Raycast(oneTouchPoint.position, MyRaycastHited, TrackableType.PlaneWithinPolygon | TrackableType.PlaneWithinBounds)) { Debug.Log("有物体被击中了"); if (Temp.gameObject==null)//判断是不是克隆过了 { Temp= GameObject.Instantiate(muban, MyRaycastHited[0].pose.position,Quaternion.identity, oneFather); } } } } }
4.3 代码的程序逻辑
1. 组件依赖:
-脚本使用 `[RequireComponent(typeof(ARRaycastManager))]` 属性来确保游戏对象上存在 `ARRaycastManager` 组件。这个组件是 AR Foundation 的一部分,用于处理射线检测和跟踪。
2. **变量声明**:
- `OnePrefab` 是一个公共变量,用于存储将要被克隆的预制体。
- `ManyHits` 是一个静态列表,用于存储射线检测的结果。
- `OneRaycastManager` 是 `ARRaycastManager` 类型的变量,用于存储获取到的 `ARRaycastManager` 组件。
- `TempObj` 是一个 `GameObject` 类型的变量,用于存储克隆后放置在地面上的物体。
3. **初始化**:
- 在 `Start` 方法中,脚本初始化 `ManyHits` 列表,并获取 `ARRaycastManager` 组件。
4. **射线检测与克隆**:
- 在 `Update` 方法中,脚本首先检查是否有触摸事件发生(`Input.touchCount`)。
- 如果有触摸事件,脚本获取第一个触摸点的信息,并使用 `OneRaycastManager` 进行射线检测。
- 如果射线检测成功击中平面(`TrackableType.PlaneWithinPolygon | TrackableType.PlaneWithinBounds`),脚本将获取第一个命中点的 `Pose`。
- 脚本随后检查 `TempObj` 是否为空。如果是空的,意味着这是第一次点击,脚本将实例化一个新的游戏对象并放置在命中点位置。
- 如果 `TempObj` 不为空,脚本将更新其位置到新的命中点。
4.4 核心算法介绍
1. **射线检测**:
- `ARRaycastManager.Raycast` 方法用于从用户触摸点发射射线,并检测射线是否击中了 AR 场景中的平面。
- 射线检测的类型由 `TrackableType` 参数指定,这里使用了 `PlaneWithinPolygon` 和 `PlaneWithinBounds` 来限制射线只检测用户定义的特定平面区域。
2. **克隆与放置**:
- 脚本使用 `GameObject.Instantiate` 方法来克隆预制体,并使用 `Pose` 来设置克隆物体的位置和旋转。
- 通过检查 `TempObj` 的状态,脚本确保用户不会重复克隆物体,除非之前的克隆物体被移除或销毁。
## 使用说明
- 将 `AppController` 脚本附加到一个游戏对象上,并确保该游戏对象上有 `ARRaycastManager` 组件。
- 在 Unity 编辑器中,将你希望克隆的预制体拖拽到 `OnePrefab` 变量上。
- 运行应用程序,通过触摸屏幕来选择位置并放置克隆的物体。
## 注意事项
- 确保你的 AR 设备或模拟器已经正确设置并支持 AR Foundation。
- 调整射线检测的类型和参数,以适应你的应用程序需求。
- 如果需要限制克隆物体的数量,可以添加额外的逻辑来管理 `TempObj` 的生命周期。
4.5 什么是TrackableType.PlaneWithinPolygon
TrackableType.PlaneWithinPolygon
是 Unity AR Foundation 中的一个枚举值,用于指定射线检测(Raycast)的目标类型。这个枚举值是 TrackableType
的一个成员,它定义了射线检测可以击中的跟踪目标类型。
在 AR 应用中,平面(Plane)是指由 AR 系统识别的环境表面,通常是水平或垂直的表面,如地板、墙壁或桌面。PlaneWithinPolygon
特指那些被定义为多边形边界内的平面。这意味着射线检测将只寻找并返回位于用户定义的多边形区域内的平面。
使用 TrackableType.PlaneWithinPolygon
可以限制射线检测的结果,使其只返回特定区域内的平面,这对于某些特定的 AR 场景和交云操作非常有用。例如,你可能只想在用户放置的特定区域(如一个虚拟房间的地面上)进行交互,而不是任何可见的平面。
在实际使用中,你可以将 TrackableType.PlaneWithinPolygon
作为参数传递给 ARRaycastManager.Raycast
方法,来指定射线检测的类型。这样,只有当射线击中了多边形区域内的平面时,射线检测才会返回命中结果。