public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance = Mathf.Infinity, int layerMask = DefaultRaycastLayers, QueryTriggerInteraction queryTriggerInteraction = QueryTriggerInteraction.UseGlobal);
origin | 世界坐标中射线的起点 |
---|---|
direction | 射线的方向 |
hitInfo | 如果返回值是true,hitInfo将包含被检测到的物体信息 |
maxDistance | 射线的最长距离 |
layerMask | 图层蒙版,用于有选择性的忽略射线 |
queryTriggerInteraction | 查询是否应该触发IsTrigger(触发器) |
bool True if the ray intersects with a Collider, otherwise false.
如果射线检测道碰撞机就返回true,否则返回false
使用射线检测,首先要给被检测物体挂Collider组件,必不可少。关于使用哪种类型的Collider根据自己的模型决定。
这里为大家测试我使用的Box Collider最基础的Collider.
下面我设计了一组对照实验,来说明Physics.Raycast各个参数所代表的意思
首先我创建了5个cube,4个被检测cube1-4,和一个射线发出cube红色的player。
cube1 的layer是默认Default没有修改,Box Collider 的Is Trigger属性没有勾选。
cube2 的layer是默认Default没有修改,Box Collider 的Is Trigger属性勾选。
cube3 的layer改成自定义的Cube层,Box Collider 的Is Trigger属性没有勾选。
cube4 的layer改成自定义的Cube层,Box Collider 的Is Trigger属性勾选。
设置完属性之后我们来射出射线吧。。。(有点。。)
先上代码
private GameObject player;
private void Awake()
{
//首先我们拿到玩家,也就是射线发出的物体
player = transform.Find("Player").gameObject;
}
//在update里持续发出射线
private void Update()
{
//获取player的position信息
Vector3 pos = player.transform.position;
//射线碰撞物信息接收
RaycastHit hit;
//第一种写法(完全按照参数的写法)
//Bool isHit =Physics.Raycast(pos, player.transform.forward,
// out hit, 5f, 1 << 0, QueryTriggerInteraction.Collide);
//第二种写法
//我们可以先创建出一条射线
Ray ray = new Ray(pos, player.transform.forward);
//然后用这条射线去做射线检测
//射线,输出碰撞体信息,射线长度,射线在那一层检测,射线不忽略开启触发器(istrigger)的碰撞体
bool isHit = Physics.Raycast(ray, out hit, 5f, 1 << 0, QueryTriggerInteraction.Collide);
//在unity窗口画出射线
Debug.DrawLine(pos,new Vector3(pos.x,pos.y,pos.z + 5) ,Color.red);
if(isHit)//如果射线检测到物体
{
//打印出被检测物体的名字
print(hit.transform.name);
}
效果如下图
我们发现当射线照射在 cube3 和cube4上的时候,isHit返回的是false, print(hit.transform.name);代码没有运行,说明射线没有检测到物体,原因也很简单,因为我们的cube3和cube4是的layer层是自定义的Cube层,但是我们代码里写的是1 << 0,这代表什么呢?这表示射线只作用于layer索引是0的layer层,而cube1和cube2的layer是Default层,对应的索引是0。所以射线成功检测到了。
现在我稍微改变一下代码。把 QueryTriggerInteraction.Collide改成Ignore
bool isHit = Physics.Raycast(ray, out hit, 5f, 1 << 0, QueryTriggerInteraction.Ignore);
效果如下图
除了cube3,cube4现在连cube2都没有被射线检测到了,这是为什么呢?因为不同于cube1,cube2的Box Collider 开启了Is Trigger属性。QueryTriggerInteraction.Ignore会忽视开启了Is Trigger属性的物体, 而QueryTriggerInteraction.Collide怎不会。
QueryTriggerInteraction还有第三个属性QueryTriggerInteraction.UseGlobal这个和上面两个的意思相同,具体看代码
//当Physics.queriesHitTriggers是false的时候QueryTriggerInteraction.UseGlobal效果等于QueryTriggerInteraction.Ignore
//当Physics.queriesHitTriggers是true的时候QueryTriggerInteraction.UseGlobal效果等于QueryTriggerInteraction.Collide
//Physics.queriesHitTriggers=false;
Physics.queriesHitTriggers=true;
QueryTriggerInteraction.UseGlobal
上面的代码,大家测试一下就清楚了。
现在说最后一点,如果同时检测多个layer层,或者只排除某个layer层不检测
1.同时检测多个层,可以这样写
// 这样可以不用1<<0这种写法 使用 LayerMask.GetMask("layer名");主要layer层的名字不要写错
bool isHit=Physics.Raycast(ray, out hit, 5, LayerMask.GetMask("Cube", "Default"));
2.除了Default层,都检测
// 在 layer参数前面加上 ~ 符号即可,两种写法都可以适用。
//bool isHit=Physics.Raycast(ray, out hit, 5, ~LayerMask.GetMask("Cube", "Default"));
bool isHit=Physics.Raycast(ray, out hit, 5, ~1<<0);
上面关于layer的知识,可以自己测试一下,注意QueryTriggerInteraction和Is Trigger的设置。
分享让知识变得有意义!后续会继续更新一些学习中问题。
OJMars
InTheMars