写在前面的话
本系列笔记旨在记录作者在学习Unity中的AR开发过程中需要记录的问题和知识点。难免出现纰漏,更多详细内容请阅读原文以及官方文档。
文章目录
- 射线检测
- 射线检测概念
- 小结
射线检测
射线检测是Unity中常见的一种物理检测方法,具体就不赘述了。除了Unity提供的Physics.Raycast()方法进行射线检测外,AR foundation还提供了AR RaycastManager组件专门用于AR中处理射线与平面、特征点的碰撞检测。
射线检测概念
射线检测通常用于在二维的屏幕上进行三维的物体检测,其简单原理就是从起始点向某一方向发射一条无限长的射线,这条射线一旦与物体的碰撞器接触就会触发检测事件。
假设要实现在手机屏幕上点击到AR plane之后,在对应位置产生一个小圆球(这就是第一章中使用到的案例),最好的方案就是射线检测。我们将摄像头的位置设置为初始点,而手指在屏幕上点击的位置视为基准点,构建一条穿过二点的射线,这条射线将触碰到其位置上的所有虚拟物体。往往射线检测的触发结果是从初始点开始触碰到的第一个物体。请看下述代码:
1. using System.Collections.Generic;
2. using UnityEngine;
3. using UnityEngine.XR.ARFoundation;
4. using UnityEngine.XR.ARSubsystems;
5.
6. [RequireComponent(typeof(ARRaycastManager))]
7. public class AppControler : MonoBehaviour
8. {
9. public GameObject spawnPrefab;
10. static List<ARRaycastHit> Hits;
11. private ARRaycastManager mRaycastManager;
12. private GameObject spawnedObject = null;
13. private void Start()
14. {
15. Hits = new List<ARRaycastHit>();
16. mRaycastManager = GetComponent<ARRaycastManager>();
17. }
18.
19. void Update()
20. {
21. if (Input.touchCount == 0)
22. return;
23. var touch = Input.GetTouch(0);
24. if (mRaycastManager.Raycast(touch.position, Hits, TrackableType.PlaneWithin Polygon | TrackableType.PlaneWithinBounds))
25. {
26. var hitPose = Hits[0].pose;
27. if (spawnedObject == null)
28. {
29. spawnedObject = Instantiate(spawnPrefab, hitPose.position, hitPose.rotation);
30. }
31. else
32. {
33. spawnedObject.transform.position = hitPose.position;
34. }
35. }
36. }
37. }
在上述代码中,Hits
是一个ARRaycastHit
的List
,它保存了所有射线Hit到的物体的信息。当触发点击事件时,mRaycastManager.Raycast
从摄像头发射一条向着touch.position
的射线,并返回所有触碰到的虚拟物体的姿态信息给Hits
,并且设置了检测的可跟踪对象为TrackableType.PlaneWithinPolygon | TrackableType.PlaneWithinBounds
(平面上的多边形或者平面带边界的平面包围盒,也就是摄像机内渲染出的可视化平面),并使用第一个检测到的平面物体的姿态信息Hits[0].pose
来初始化预制体。
在ARFoundation中,目前射线检测只能用来检测平面和点云。ARFoundation中的射线检测与Unity中Physics模块使用的射线检测相似,但提供了独立的接口,在ARFoundation中使用射线检测需要ARRaycastManager组件,因为射线检测与被检测物体需要在同一个坐标空间中,所以该组件需要挂载在ARSessionOrigin对象上。
————————————————
版权声明:本文为CSDN博主「DavidWang」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yolon3000/article/details/94458183
射线检测方法 | 说明 |
---|---|
public bool Raycast(Vector2 screenPoint, List hitResults, TrackableType trackableTypeMask = TrackableType.All) | 参数1为屏幕坐标点,参数2为所有与射线发生碰撞的对象列表,参数3为Trackable类型掩码(即只对该类或几类可跟踪对象进行射线检测),该方法的返回值为Bool型,true表示发生碰撞,false表示未发生碰撞。 |
public bool Raycast(Vector2 screenPoint, List hitResults, TrackableType trackableTypeMask = TrackableType.All) | 参数1为Ray类型的射线(包括位置与方向),参数2为所有与射线发生碰撞的对象列表,参数3为Trackable类型掩码(即只对该类或几类可跟踪对象进行射线检测),该方法的返回值为Bool型,true表示发生碰撞,false表示未发生碰撞。 |
trackableTypeMask 用来过滤需要进行碰撞检测的对象类型,Trackable类型其值可以是以下属性值的一个,也可以是几个,如果是几个,可以采用按位或,如TrackableType.PlaneWithinPolygon | TrackableType.FeaturePoint。
trackableType 属性 | 说明 |
---|---|
All | 这个值用于与放置的所有物体发生碰撞检测。如果我们填写这个值,那么在ARFoundation中,我们发射的射线将与场景中的所有平面、包围多边形、带法线的特征点进行碰撞检测。 |
FeaturePoint | 与当前帧点云中所有的特征点进行碰撞检测。 |
None | 此值用来表示trackableHit返回中没有碰撞发生,如果将此值传递给raycast,则不会得到任何碰撞结果。 |
PlaneWithinPolygon | 与已检测平面内的凸边界多边形进行碰撞检测。 |
PlaneWithinBounds | 与当前帧中已检测平面内的包围盒进行碰撞检测。 |
PlaneWithinInfinity | 与已检测到的平面进行碰撞检测,但这个检测不仅仅局限于包围盒或者多边形,而是可以与已检测到的平面的延展平面进行碰撞检测。 |
FeaturePointWithSurfaceNormal | 射线与评估平面进行碰撞检测,评估平面不一定能形成一个平面。 |
Planes | 射线与以上所有平面类型进行碰撞检测。 |
Image | 与2D图像进行射线检测。 |
Face | 与人脸进行射线检测。 |
ARRaycastHit类保存的是发生碰撞时检测到的碰撞体相关信息,其主要属性如下表所示。
ARRaycastHit 属性 | 说明 |
---|---|
Distance | float类型,获取从射线源到命中点的距离 |
trackableId | 发生碰撞的可跟踪对象ID。 |
Pose | Pose类型,获取射线击中的物体在Unity世界坐标中的姿态。 |
hitType | Trackable类型,获取命中的可跟踪对象,即前文所述的七种可跟踪类型之一(实际上,目前ARFoundation只能对平面与特征点做射线检测)。 |
sessionRelativeDistance | 在Session空间中从射线起点到碰撞点的距离。 |
sessionRelativePose | 在Session空间碰撞点的姿态。 |
小结
使用AR RaycastHit可以用来专门处理AR空间中的射线检测信息。由于姿态信息都保存在了AR Session Rigion组件上,因此AR Raycast Manager也要挂载在该对象上。
AR RaycastHit可以获取到三维空间上所有的射线触碰到的姿态信息。我们总结了两个射线检测方法以及其参数信息,使用射线检测来实现一些基本的功能。
(作者本人的博客比官方文档写的详细多了)