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

本文介绍了Unity中LayerMask的概念和应用场景,包括如何通过LayerMask进行图层选择过滤,如使用LayerMask.GetMask和位运算符来组合图层。在物理检测和碰撞时,LayerMask能帮助限制检测范围,提高性能。文章还提供了多个实例,展示了如何根据需求选择不同的图层进行检查。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

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

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不等价,但是可以通过移位来处理。

### LayerMask使用方法及应用场景 #### 使用方法Unity 中,`LayerMask` 主要用于指定哪些图层参与特定的操作。通过 `LayerMask.GetMask()` 方法可以根据图层数组或图层名来创建遮罩值[^1]。 对于给定的图层名称,可以通过调用静态函数 `GetMask(string[] layerNames)` 或者 `NameToLayer(String layerName)` 来获得对应的整数值表示形式。这个值实际上是基于二进制位运算的结果,即每一层对应着不同的指数幂次方数(2^n),其中 n 表示该层的位置索引。例如: - 如果有一个名为 "UserLayerA" 的自定义层位于第 10 层,则它的遮罩值将是 \(2^{10}=1024\); - 同样地,“UserLayerB”处于第 11 层时,其遮罩值应为 \(2^{11}=2048\)[^2]; 当需要组合多个图层作为输入参数传递给某些 API 函数时,可以直接将这些图层的名字放入到一个字符串数组里并传入 `GetMask()` 函数中去计算最终的掩码值。比如想要同时选取 “Ground”,“Water” 和 “Player” 图层的话就可以这样做: ```csharp int mask = LayerMask.GetMask(new string[]{"Ground", "Water", "Player"}); ``` #### 应用场景 最典型的例子就是在物理系统的射线投射操作 Physics.Raycast() 上的应用。此功能允许开发者发射一条虚拟光线,并检测它是否与其他物体发生碰撞接触。此时便可以用到 `LayerMask` 参数来自定义希望这条光线能够穿透或者忽略掉哪些类型的对象。如下所示,在执行一次地面检测的过程中只考虑属于 Ground 类别的实体: ```csharp if (Physics.Raycast(transform.position, Vector3.down, out RaycastHit hitInfo, Mathf.Infinity, LayerMask.GetMask("Ground"))) { Debug.Log($"Hit ground at position {hitInfo.point}"); } ``` 除了上述提到的例子之外,其他可能涉及到的地方还包括但不限于光照剔除、摄像机视锥体裁剪等方面。总之任何地方只要存在按类别筛选的需求都可以利用好这一特性提高效率和灵活性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

就一枚小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值