写在前面的话
本系列笔记旨在记录作者在学习Unity中的AR开发过程中需要记录的问题和知识点。难免出现纰漏,更多详细内容请阅读原文。
本文从原文第二章开始
ARFoundation的整个体系建立在一系列的Subsystem(子系统)上,每个子系统对应实现不同的模块功能。由于不同的AR设备提供的SDK不同,因此ARfoundation的子系统类似于提供了一系列的接口让不同厂商可以在同一套应用标准下对接他们的AR设备。
在本系列中我们需要使用的主要是安卓的ARcore(Google play的AR服务)以及苹果的ARKit。第一次使用AR程序的demo在该书的第一章节已经给出。
当然,不同的厂商对应能提供的服务也不同,因此ARfoundation提供了SubsystemDescriptor让厂商们自行标识出那些子系统是可用的。
所有的Subsystem都有四个生命周期:创建(Create),开始(Start),停止(Stop),销毁(Destroy)。通过获取状态来在程序中判断子系统的活动。
当然,要激活子系统,我们需要获取SubsystemDescriptor描述符来判断子系统是否可用。下列是一段示例代码:
1. XRPlaneSubsystem CreatePlaneSubsystem()
2. {
3. // 得到所有可用的plane subsystems:
4. var descriptors = new List<XRPlaneSubsystemDescriptor>();
5. SubsystemManager.GetSubsystemDescriptors(descriptors);
6. // 遍历获取一个支持boundary vertices的功能
7. foreach (var descriptor in descriptors)
8. {
9. if (descriptor.supportsBoundaryVertices)
10. {
11. // 创建plane subsystem
12. return descriptor.Create();
13. }
14. }
15. return null;
16. }
通过SubsystemManager中的获取描述符List的方法GetSubsystemDescriptors,我们得到了所有可用的子系统,并遍历检测其子系统是否支持boundary vertices,若遍历过程中发现是支持的,则对其进行子系统的创建。以实现我们想要实现的功能。
Create()方法是一个单例模式的创建,想要控制AR中的一些功能,我们无需对GameObject进行一些消耗性能的操作,只需要手动控制子系统的生命周期即可:
1. var planeSubsystem = CreatePlaneSubsystem();
2. if (planeSubsystem != null)
3. {
4. // 开始平面检测
5. planeSubsystem.Start();
6. }
7.
8. if (planeSubsystem != null)
9. {
10. // 停止平面检测,但这并不会影响到已检测到的平面
11. planeSubsystem.Stop();
12. }
13.
14. if (planeSubsystem != null)
15. {
16. // 销毁该subsystem
17. planeSubsystem.Destroy();
18. planeSubsystem = null;
19. }
上述代码展示了一个子系统从创建到停止到销毁的生命过程。
一些子系统可用实现对物理环境的实时检测和跟踪,被称为跟踪子系统(Tracking subsystem),例如平面跟踪和图像跟踪,被跟踪的对象被称为可跟踪对象(Trackable),每个Trackable对象都拥有独特的ID作为标识。
在ARfoundation中,每类跟踪子系统都提供了getchanges()方法,用于获取被跟踪物体的状态信息变化。跟踪子系统也可以手动添加,更新或者移除Trackable对象。在跟踪子系统的manager类中通常提供了一些xxxChanged事件或者xxxChangedEventArgs的Event来对状态变化进行处理。
在第一章节的demo中,创建AR程序的第一步是先创建ARSession和ARSessionOrigin两个对象,这两个对象支撑起了AR应用最基础的框架。我们将要学习这两个对象的作用。
AR Session主要包括两个组件,一个就是AR Session,管理Session,另一个是AR Input Manager,管理输入相关信息。
Session用于管理AR应用的状态,处理生命周期,是AR API的主要入口,常用于控制AR程序。
AR Input Manager组件是启用环境跟踪的必需组件,若不启用此组件,Tracked Pose Driver(跟踪姿态驱动)将无法获取设备的姿态。
在任何一个AR应用中,有且只有一个Session,Unity将Session设成全局组件,因此如果场景中有多个AR Session,这些AR Session将尝试管理同一个Session。同理AR Input Manager也有且只有一个。
由于并不是每一个设备都支持AR功能,AR Session提供了AR Session State 枚举类型来标识当前Session的状态。开发人员可用根据状态来定义XXX的状态事件。
ARSessionState | 描述 |
---|---|
CheckingAvailability | 应用正在检测设备可用性 |
Installing | AR软件正在安装(这里指移动端的ARCore或者ARKit) |
NeedsInstall | 设备支持AR,但需要安装相应软件(这里指移动端的ARCore或者ARKit) |
None | 应用还未完成初始化,设备可用性未知 |
Ready | AR应用可用并已经准备好 |
SessionInitializing | AR Session正在初始化,通常指AR在设备上可用,但AR应用目前还未收集到足够的环境信息 |
SessionTracking | Session正常运行并且处于正常跟踪状态 |
Unsupported | 设备不支持AR |
通过状态类型,来检测AR应用在启动时的状态,并选择不同的处理方式:
1. IEnumerator CheckSupport()
2. {
3. Debug.Log("检查设备...");
4. yield return ARSession.CheckAvailability();
5. if (ARSession.state == ARSessionState.NeedsInstall)
6. {
7. Debug.Log("设备支持AR,但需要更新...");
8. Debug.Log("尝试更新...");
9. yield return ARSession.Install();
10. }
11. if (ARSession.state == ARSessionState.Ready)
12. {
13. Debug.Log("设备支持AR!");
14. Debug.Log("启动AR...");
15.
16. // To start the ARSession, we just need to enable it.
17. m_Session.enabled = true;
18. }
19. else
20. {
21. switch (ARSession.state)
22. {
23. case ARSessionState.Unsupported:
24. Debug.Log("设备不支持AR.");
25. break;
26. case ARSessionState.NeedsInstall:
27. Debug.Log("更新失败.");
28. break;
29. }
30. //
31. // 启动非AR的替代方案......
32. //
33. }
34. }
35.
36. void SetInstallButtonActive(bool active)
37. {
38. if (m_InstallButton != null)
39. m_InstallButton.gameObject.SetActive(active);
40. }
41.
42. IEnumerator Install()
43. {
44. if (ARSession.state == ARSessionState.NeedsInstall)
45. {
46. Debug.Log("尝试安装ARCore服务...");
47. yield return ARSession.Install();
48.
49. if (ARSession.state == ARSessionState.NeedsInstall)
50. {
51. Debug.Log("ARCore服务更新失败.");
52. SetInstallButtonActive(true);
53. }
54. else if (ARSession.state == ARSessionState.Ready)
55. {
56. Debug.Log("启动AR...");
57. m_Session.enabled = true;
58. }
59. }
60. else
61. {
62. Debug.Log("无需安装.");
63. }
64. }
65.
66. void OnEnable()
67. {
68. StartCoroutine(CheckSupport());
69. }
AR Session Origin对象默认有一个Transfrom组件和一个AR Session Origin组件
AR Session Origin中组件的作用是将可跟踪对象(如平面和特征点)姿态信息转换为Unity场景中的位置信息。由于AR设备由Session进行管理,因此Trackable对象的姿态信息会被获取到称为Session Space的初始空间,再通过AR Session Origin完成对姿态信息到Unity坐标空间的映射变换。
AR Session Origin的面板上还接收一个AR摄像机。
在AR Camera上,默认挂载了以上组件。
其中Tracked Pose Driver组件的主要作用是将Unity中的场景摄像机与设备的真实摄像机对齐,即根据设备真实摄像机的位置与方向来调整Unity中的场景摄像机姿态。使得Unity中的摄像机和AR设备的摄像机有用一致的参数,保证unity中的虚拟坐标和现实世界的坐标相对应。
在AR Foundation3.0以后,Tracked Pose Driver组件已被AR Pose Driver取代,AR Pose Driver没有任何控制参数,它会自动处理所有与场景姿态相关的工作。
AR Camera Manager组件负责处理控制摄像机的一些细节参数,如表示纹理和控制光照估计模式,其有两个参数,Focus Mode和Light Estimation Mode,相关属性如下表所示:
随后是AR Camera BackGround组件,该组件的两个参数:Use Custom Material 和 Use Custom Render Asset 均为可选参数,用于进行背景渲染。
每个AR Session Origin都可以通过添加AR Camera Background将摄像机图像渲染为场景。如果程序中存在多个AR Session Origin和多个摄像机,则需要为每一个AR Session Origin和每一个AR Camera都指定AR Camera Background。
在本章中,我们学习了ARFoundation的一些基本结构(例如Subsystem,trackable)和用法,初步了解了AR Session和AR Session Origin两个基本组件,其中AR Session属于全局管理AR 程序的核心部分,控制整个AR的生命周期。而AR Session Origin 则用于相关的AR摄像机渲染,物体追踪等工作。