射线检测Raycast
- 射线检测是一种常用的技术,用于检测游戏中的碰撞、交互等情况。Unity提供了几种不同的射线检测方法,包括射线检测、球形射线检测和盒形射线检测。
一、发射一条射线
- 向屏幕中某处发射一条射线,体现在3D游戏空间中,即从视角摄像机开始向着空间中指定的某处发射一条射线
1.射线的定义
Ray ray = new Ray(Vector3.zero, Vector3.up);
// 创建一条射线,从摄像机位置发出,并沿着摄像机的正方向向着鼠标点击的方向进行射线检测
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
2.实现发射射线检测碰撞触发
//声明一个碰撞信息类
RaycastHit hitInfo;
//碰撞检测事件
bool res=Physics.Raycast(ray, out hitInfo);
//如果有射线碰撞输出内容
if(res)
{
// 如果射线与物体发生碰撞,可以通过hitInfo获取碰撞的相关信息
Debug.Log("Hit object: " + hitInfo.collider.gameObject.name);
Debug.Log("Hit point: " + hitInfo.point);
Debug.Log("Hit normal: " + hitInfo.normal);
}
-
hitInfo.normal
:用于获取碰撞点的法线向量。返回的是一个单位向量(长度为1),如果需要使用具有不同长度的法线向量,可以根据需要进行缩放。
-
Physics.Raycast(ray, out hitInfo)
是在Unity中进行射线检测的常用函数之 一。它接受一个Ray
类型的参数和一个out RaycastHit
类型的参数,用于检测从Ray
的起点开始沿着Ray
的方向是否与场景中的物体相交,并将检测到的信息存储在RaycastHit
对象中。- 具体来说,
ray
参数是一条射线,它是从摄像机或其他位置发出的,它有一个起点和一个方向。hitInfo
参数是一个传出参数,用于存储检测到的信息,包括碰撞的物体、碰撞点的位置、碰撞表面的法线等。
- 当调用
Physics.Raycast(ray, out hitInfo)
时,Unity会检测从ray
的起点开始沿着ray
的方向是否与场景中的物体相交,如果相交,则将检测到的信息存储在hitInfo
中,然后返回true
。如果没有相交,则返回false
。
撞的物体、碰撞点的位置、碰撞表面的法线等。
- 在使用
Physics.Raycast(ray, out hitInfo)
进行射线检测时,需要注意以下几点:
- 射线检测的结果只与场景中的物体相关,与摄像机和其他相关因素无关。
- 如果一条射线与多个物体相交,可以使用
Physics.RaycastAll
函数来获取所有的碰撞信息。 - 在使用
Physics.Raycast
进行射线检测时,需要保证射线的方向向量是归一化的,否则可能会出现意外的结果。
- 具体来说,
二 、发射多条射线
1.多条射线定义
RaycastHit[] hitInfos=Physics.RaycastAll(ray);
2.检测特定距离100
RaycastHit[] hitInfos=Physics.RaycastAll(ray,100);
3.只检测特定图层
RaycastHit[] hitInfos=Physics.RaycastAll(ray,100,1<<10);
- 在Unity引擎中,最多只存在0~31共32个图层,图层layerMask是一个32位整数,因此在向函数传参时,对层数的选择要使用位运算传入。
4.layerMask的传参
用位运算操作可以快速创建或修改指定图层的 LayerMask,以下是一些示例:
1. 创建只包含第 0 层的 LayerMask:
int layerMask = 1 << 0;
其中 <<
是左移运算符,表示将二进制数向左移动指定的位数。在这个例子中,将数字 1 向左移动 0 位,得到的结果是 00000001,即十进制数 1。因此,第 0 层的 LayerMask 值为 1。
2. 创建只包含第 1 层和第 2 层的 LayerMask:
int layerMask = (1 << 1) | (1 << 2);
这里使用了按位或运算符 |
,将两个数字的对应的二进制位进行或运算。在这个例子中,将数字 1 分别向左移动 1 位和 2 位,得到的结果分别是 00000010 和 00000100。然后将这两个数进行按位或运算,得到的结果是 00000110,即十进制数 6。因此,第 1 层和第 2 层的 LayerMask 值为 6。
3. 将第 3 层添加到 LayerMask 中:
layerMask = layerMask | (1 << 3);
这里使用了按位或运算符 |
,将原来的 LayerMask 值与数字 1 左移 3 位的结果进行或运算。在这个例子中,如果原来的 LayerMask 值为 6(即第 1 层和第 2 层),左移 3 位的结果是 00001000。然后将这个数与 6 进行按位或运算,得到的结果是 00001110,即十进制数 14。因此,第 1 层、第 2 层和第 3 层的 LayerMask 值为 14。
4. 将第 2 层从 LayerMask 中移除:
layerMask = layerMask & ~(1 << 2);
这里使用了按位与运算符 &
和按位取反运算符 ~
,将原来的 LayerMask 值与数字 1 左移 2 位的按位取反的结果进行按位与运算。在这个例子中,如果原来的 LayerMask 值为 14(即第 1 层、第 2 层和第 3 层),左移 2 位的结果是 00000100。然后将这个数按位取反,得到的结果是 11111011。最后将这个数与 14 进行按位与运算,得到的结果是 00001010,即十进制数 10。因此,第 1 层和第 3 层的 LayerMask 值为 10。s