按位与的这种,层计算方式,很多人博客都写了,估计你查了很多篇资料才翻到我这,所以按位与计算不在本篇重点。

这是官方中文文档 https://connect.unity.com/doc/Manual/Layers 可以看一下。

那么为什么按照官方文档,按位与,计算好层,传给Physics.Raycast中的layerMask后,

依然没什么卵用!

写好的逻辑,毫无效果!

为什么!

 

首先,感谢下面链接作者文章的最后一句话


 

传入LayerMask参数没有效果,是因为Physics.Raycast参数中,没有传入maxDistance

传入LayerMask参数没有效果,是因为Physics.Raycast参数中,没有传入maxDistance

传入LayerMask参数没有效果,是因为Physics.Raycast参数中,没有传入maxDistance

Unity碰撞层级穿透 unity添加碰撞层_Unity碰撞层级穿透

 

即使你不需要maxDistance这个参数,也要传进去(这里我使用的unity版本是2019.2.11)

像这样,随便传入个1000,作为参数

Physics.Raycast(ray,out hit,1000, mask)

 

而反观官方文档,他们在maxDistance处,确实都传了Mathf.infinity

Unity碰撞层级穿透 unity添加碰撞层_Unity碰撞层级穿透_02

然鹅,他们并没有说明。

 

基本,看到这,标题的问题就解决了。如果想看其它基础知识,请往下

 

 

其次,贴一下按位与的基本知识

1 << 9                              打开第9层。
~(1 << 9)                         打开除了第9之外的层。
~(1 << 0)                         打开所有的层。
(1 << 10) | (1 << 8)          打开第10和第8的层。

 

 

关于LayerMask这里要传什么样的参数

Unity碰撞层级穿透 unity添加碰撞层_射线_03

1.传入int型

直接按照上面,按位与基本知识,传入想要打开射线碰撞检测的层即可。

例如我只想射线与第8层交互,其它全部穿过忽略

Physics.Raycast(ray,out hit,1000, (1 << 8))

 

 若不使用按位与,直接输入一个Int到LayerMask,那么unity会忽略你输入的这个层,这个层的index与Tag & Layer中的关系是+1的。

比如,我想忽略Floor层,我们要传入9,而不是8!

Physics.Raycast(ray,out hit,1000, 9)

 

2.传入LayerMask类型

这种非常直观,而且容易编辑,共有参数可以在Inspector中编辑想要交互的层

Unity碰撞层级穿透 unity添加碰撞层_layer层_04

其次,如果想要代码为其赋值,可以

public LayerMask mask;

void Start()
{
    mask = (1 << 8) | (1 << 11);
}

这是,指定Floor层和C层,参与交互

 

 

这是我的一个例子

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LLL : MonoBehaviour
{
    LineRenderer lineRender;
    Ray ray;
    RaycastHit hit;
    Transform point;
    public string TeleableTag = "";
    public int mlayer = 0;
    public LayerMask mask;

    void Start()
    {
        point = transform;

        lineRender = GetComponent<LineRenderer>();
        lineRender.startWidth = 0.05f;
        lineRender.endWidth = 0.05f;
        lineRender.useWorldSpace = false;
        lineRender.material = new Material(Shader.Find("Standard"));

        mask = (1 << 8) | (1 << 11);
    }

    void Update()
    {
        ray = new Ray(point.position, point.transform.forward);

        //;
        //

        if (Physics.Raycast(ray,out hit,1000, mask)) {
            if (hit.transform.tag == TeleableTag) {//
                                                   //可传送
                LinernederTeleable();
            }
            else {
                //Tag验证未通过,不可传送
                LinerenderUnTeleable();
            }
        }
        else {
            //不可传送
            LinerenderUnTeleable();
        }
    }

    private void LinernederTeleable() {
        //linerender 结束点=hit  颜色=green
        lineRender.SetPosition(1, new Vector3(0, 0, Vector3.Distance(point.position, hit.point)));
        Debug.Log("point=" + hit.point + " distance=" + Vector3.Distance(point.position, hit.point));
        lineRender.materials[0].color = Color.green;
        Debug.Log(hit.transform.name);
    }

    private void LinerenderUnTeleable() {
        //linerender 结束点=很大  颜色=red
        if (hit.transform.gameObject == null)
            lineRender.SetPosition(1, new Vector3(0, 0, 1000));
        else
            lineRender.SetPosition(1, new Vector3(0, 0, Vector3.Distance(point.position, hit.point)));
        lineRender.materials[0].color = Color.red;
    }
}

运行结果

Unity碰撞层级穿透 unity添加碰撞层_按位与_05

Unity碰撞层级穿透 unity添加碰撞层_按位与_06