Unity学习笔记--LayerMask的使用方法和易错点

Posted 就一枚小白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity学习笔记--LayerMask的使用方法和易错点相关的知识,希望对你有一定的参考价值。

目录

前言

最近需要使用代码来动态获取某一个游戏对象的图层等。学习了下,来此记录。

LayerMask简介

  1. 首先来说说Layer:图层。其实就是下方这个。

  2. LayerMask直译过来就是图层蒙版。具体是什么意思我们来看看具体的例子就明白了。

例子

我们在使用Unity提供的物理系统的时候,经常需要发射射线或者检测碰撞体等等。
比如下面这个方法

public static Collider[] OverlapBox (
			Vector3 center, Vector3 halfExtents, 
			Quaternion orientation= Quaternion.identity, int layerMask= AllLayers, 
			QueryTriggerInteraction queryTriggerInteraction= QueryTriggerInteraction.UseGlobal
);

描述
查找与给定盒体接触或位于盒体内部的所有碰撞体。
创建一个您定义的不可见盒体,通过输出与该盒体发生接触的任何碰撞体来测试碰撞。

这个方法的第四个参数是layerMask,意思是
你指定一些图层,让你的OverlapBox只能对于指定的layerMask做检查,如果该碰撞体的图层是你指定的图层,那么就加入到返回结果中;反之即使这个碰撞体符合要求,也不会加入到返回结果中。

怎么获取LayMask

如果我们只知道Layer的名字,怎么获取呢?

方法一

使用方法LayerMask.GetMask

public LayerMask m_LayerMask = LayerMask.GetMask(new string[]"Default", "Hit");

方法二

使用二进制位运算符按位或 : “|”

public LayerMask m_LayerMask = LayerMask.GetMask("Default") | LayerMask.GetMask("Hit");

方法三

LayerMask.NameToLayer是获得该层的在列表中的索引,实际值通过GetMask获取,若想要把索引转换为实际值,可以通过移位操作获得

上面这句话的意思是:LayerMask.NameToLayer获取的是所有,也就是你点击任意游戏对象的Layer,有很多图层供你选择,左边的数字就是索引。

注意:但是实际的LayMask并不是按索引存储的,而是二进制存储。例如Hit的索引是2,那么它具体存的数值就是1 << 2 = 4,所以你LayerMask.NameToLayer(“Hit”)的值就是4而不是2 。所以在使用NameToLayer的时候需要移位。

public LayerMask m_LayerMask = 
			(1 << LayerMask.NameToLayer("Default")) | (1 << LayerMask.NameToLayer("Hit"));

使用场景

比如我现在有几个图层,分别是

  • Layer_one
  • Layer_two
  • Layer_three

场景一

我现在只需要让Layer_one图层的游戏对象参与UnityEngine.Physics.OverlapBox的检查。
那我可以这样

public LayerMask m_LayerMask = LayerMask.GetMask("Layer_one");

public bool Check()

	Collider[] res = UnityEngine.Physics.OverlapBox(transform.position, transform.localScale / 2, UnityEngine.Quaternion.Identity, m_LayerMask);
	return res.Length > 0;


场景二

需要让Layer_one图层和Lay_two的游戏对象参与UnityEngine.Physics.OverlapBox的检查。
那我可以这样

public LayerMask m_LayerMask = LayerMask.GetMask("Layer_one") | LayerMask.GetMask("Lay_two");

public bool Check()

	Collider[] res = UnityEngine.Physics.OverlapBox(transform.position, transform.localScale / 2, UnityEngine.Quaternion.Identity, m_LayerMask);
	return res.Length > 0;


总结

需要注意的点是LayMask.GetMask和LayerMask.NameToLayer不等价,但是可以通过移位来处理。

Unity3D中Layers和LayerMask解析

Unity中是用int32来表示32个Layer层。int32表示二进制一共有32位(0—31)。
在Unity中可编辑的Layer如下图所示:

在Unity中每个GameObject都有Layer属性,默认的Layer都是Default。在Unity中可编辑的Layer共有24个(8—31层),官方已使用的是0—7层,默认不可编辑!

LayerMask实际上是一个位码操作,在Unity3D中一共有32个Layer层,并且不可增加。

位运算符

按位运算符:~、|、&、^。位运算符主要用来对二进制位进行操作。

逻辑运算符:&&、||、!。逻辑运算符把语句连接成更复杂的复杂语句。

按位运算符:左移运算符<<,左移表示乘以2,左移多少位表示乘以2的几次幂。

举个栗子:

var temp = 14 << 2; 表示十进制数14转化为二进制后向左移动2位。

temp最后计算的值为 14乘以2的平方,temp = 56;

同理,右移运算符>>,移动多少位表示除以2的几次幂。

具体可以转到博客:按位运算符.

上面是个基础知识的补充。

在Unity中是用LayerMask

Layers

官方给出的描述是:Layers are most commonly used by Cameras to render only a part of the scene, and by Lights to illuminate only parts of the scene. But they can also be used by raycasting to selectively ignore colliders or to create collisions。

翻译下就是:Layers通常被摄像机用来渲染部分场景,和灯光照射部分场景使用。但是它们也可以用来做射线检测时忽略一些collder或Collision使用。

如何编辑Layers.

在代码中使用时如何开启某个Layers?

LayerMask mask = 1 << 你需要开启的Layers层。

LayerMask mask = 0 << 你需要关闭的Layers层。

举几个个栗子:

LayerMask mask = 1 << 2; 表示开启Layer2。

LayerMask mask = 0 << 5;表示关闭Layer5。

LayerMask mask = 1<<2|1<<8;表示开启Layer2和Layer8。

LayerMask mask = 0<<3|0<<7;表示关闭Layer3和Layer7。

上面也可以写成:

LayerMask mask = ~(1<<3|1<<7);表示关闭Layer3和Layer7。

LayerMask mask = 1<<2|0<<4;表示开启Layer2并且同时关闭Layer4.

代码:

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    LayerMask mask =  ~(1<<3|1<<7);
    void Update() {
        if (Physics.Raycast(transform.position, transform.forward, 100, mask.value))
            Debug.Log("Hit something");

    }
}

以上是关于Unity学习笔记--LayerMask的使用方法和易错点的主要内容,如果未能解决你的问题,请参考以下文章

Unity2D重叠圆LayerMask不起作用

Unity3D中Layers和LayerMask解析

Unity LayerMask 的位运算

[Unity]Ray射线物理检测碰撞和LayerMask的使用

[Unity]Ray射线物理检测碰撞和LayerMask的使用

带有 LayerMask 的 Unity Physics.Raycast 不会检测图层上的对象。使用了位移,尝试了反相层,仍然没有任何效果