Unity - 射线检测

403 阅读2分钟

射线检测

物理系统中,我们目前学习的物体相交判断。

  1. 碰撞检测:必备条件:1.刚体;2.碰撞器
  2. 范围检测:必备条件:1.碰撞器

如果想要 1. 鼠标选择场景上的一个物体;2.FPS射击游戏(无弹道,不产生实际的字段对象进行移动)等,需要判断一条线和物体的碰撞情况。这个时候就可以使用射线检测了。他可以在指定点发射一个指定方向的射线,判断该射线与哪些碰撞器相交,然后得到对应的对象。

 

射线对象

//参数含义
//参数1:起点
//参数2:方向(一定记住第二个参数不是终点,而是一个方向向量)
//这样申明一个射线对象对我们来说没有任何作用
Ray ray = new Ray(Vector3.zero, Vector3.up);
print(ray.origin);
print(ray.direction);

摄像机发射的射线

//得到一条从屏幕位置为起点,摄像机视口方向为方向的射线
//注意:单独的射线对我们来说没有实际意义,我们需要用他结合物理系统进行射线碰撞判断
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

碰撞检测函数

Physics类中提供了很多进行射线检测的静态函数,他们有很多种重载类型。

注意:射线检测也是瞬时的,只有在执行代码时进行一次射线检测

//1.准备一条射线
Ray ray = new Ray(Vector3.zero, Vector3.forward);
//2.进行射线检测,如果碰到对象就返回true
//参数1:射线
//参数2:检测的最大距离
//参数3:检测指定层级(不填检测所有层)
//参数4:是否忽略触发器。UseGlobal- 使用全局设置  Collide-检测触发器 Ignore-忽略触发器 不填默认UseGlobal
//返回值:true:碰撞到对象;false:未碰撞
if(Physics.Raycast(ray,1000,1<< LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal))
{
    print("碰撞到了对象");
}

还有一种重载,直接传起点和方向,也可用于判断

//就是把第一个参数Ray换成起点和方向
if(Physics.Raycast(Vector3.zero, Vector3.forward, 1000,1<< LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal))
{
      print("碰撞到了对象");
}

获取第一个碰撞到的物体信息

Ray ray = new Ray(Vector3.zero, Vector3.forward);
//物体信息类RaycastHit 
//他不仅可以得到我们碰撞到的物体信息,还可以得到碰撞到的点,距离,法线等信息。有了法线信息,我们可以在碰撞点贴图的时候知道旋转角度。
RaycastHit hit;
//参数:
//射线
//RaycastHit是结构体,属于值类型,Unity会通过out关键字在函数内部处理后,得到碰撞数据后返回给该参数
//距离
//检测指定层级
//是否忽略触发器
if (Physics.Raycast(ray,out hit ,1000,1<< LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal))
{
	print("碰撞到了对象");
	//碰撞体信息
	print(hit.collider.gameObject.name);

	//碰撞到的点
    print(hit.point);

	//距离
    print(hit.distance);

	//法线
    print(hit.normal);
    //碰撞到的物体的位置
    print(hit.transform.position);
}

重载

//与上面的另一个重载类似
if (Physics.Raycast(Vector3.zero, Vector3.forward,out hit ,1000,1<< LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal))
{
	
}

获取多个碰撞到的物体

Ray ray = new Ray(Vector3.zero, Vector3.forward);

//参数与上面一致,就是返回值不一样。这里返回的是所有碰撞到的物体
RaycastHit[] hits = Physics.RaycastAll(ray, 1000, 1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);
foreach (var hit in hits)
{
    print("碰撞到的物体名字" + hit.collider.gameObject.name);
}

另外重载也是将Ray换成起点和方向,就不赘述了。

还有一种函数,是通过out得到 碰撞到的物体的数量

Ray ray = new Ray(Vector3.zero, Vector3.forward);

RaycastHit[] hits = new RaycastHit[] { };
int count = Physics.RaycastNonAlloc(ray, hits, 1000, 1 << LayerMask.NameToLayer("Default"), QueryTriggerInteraction.UseGlobal);
//当count大约0,表示有碰撞到物体
if (count > 0)
{
    print("有碰撞到物体");
}

qrcode.jpg