Unity学习之Physic.Raycast(射线检测)个人理解分享

Physics.Raycast参数

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.
Unity学习之Physic.Raycast(射线检测)个人理解分享_第1张图片
下面我设计了一组对照实验,来说明Physics.Raycast各个参数所代表的意思
Unity学习之Physic.Raycast(射线检测)个人理解分享_第2张图片
首先我创建了5个cube,4个被检测cube1-4,和一个射线发出cube红色的player。
Unity学习之Physic.Raycast(射线检测)个人理解分享_第3张图片
cube1 的layer是默认Default没有修改,Box Collider 的Is Trigger属性没有勾选。
Unity学习之Physic.Raycast(射线检测)个人理解分享_第4张图片
cube2 的layer是默认Default没有修改,Box Collider 的Is Trigger属性勾选。
Unity学习之Physic.Raycast(射线检测)个人理解分享_第5张图片
cube3 的layer改成自定义的Cube层,Box Collider 的Is Trigger属性没有勾选。
Unity学习之Physic.Raycast(射线检测)个人理解分享_第6张图片
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。所以射线成功检测到了。
Unity学习之Physic.Raycast(射线检测)个人理解分享_第7张图片

现在我稍微改变一下代码。把 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

你可能感兴趣的:(unity学习)