一:前言
在项目中有的时候,希望一些游戏对象只能被某些摄像机看到或者只会被某些灯光照亮,就需要用到Unity中Layer层级
Unity用int32来表示32个层:0000 0000 0000 0000 0000 0000 0000 0000,1表示开启,0表示关闭,实际的LayerMask值是通过二进制存储的
二:位运算符
位运算符是对二进制进行运算的运算符
——与运算符:只有两个位都是1,结果才是1
——或运算符:只要两个位有一个是1,结果就是1
——非运算符:如果位为0,结果是1,如果位为1,结果是0
——异或运算符:两个操作数的位中,相同则结果为0,不同则结果为1
——左移运算符<<:左移多少位表示乘以2的几次幂
——右移运算符>>:右移多少位表示除以2的几次幂
使用位运算符的几个小例子:
——判断一个数是否为偶数:if (0 == (a & 1))
——判断一个数是否为奇数:if (1 == (a & 1))
——不使用临时变量,交换两个数a=1,b=2; a=a^b; b=a^b; a=a^b;
因为,一个数和自己进行异或运算,得到的是0。一个数和0进行异或运算,得到的还是这个数。
三:常用方法
——LayerMask.GetMask
获取到的是一个int值,这个值称为等效图层蒙版,其实是二进制值对应的十进制值,例如LayerMask.GetMask("UI"),获取到的值是32,转换为二进制后为0010 0000,表示第五层
——LayerMask.LayerToName
传入层级的index,获取到层级名称
——LayerMask.NameToLayer
传入层级的名称,获取到层级的index
——设置Layer
LayerMask mask=1<<需要开启的Layers层
LayerMask mask=0<<需要关闭的Layers层
开启第5层
LayerMask mask=1<<5或LayerMask mask=1<<LayerMask.NameToLayer("UI")
关闭第五层
LayerMask mask=0<<5或LayerMask mask=0<<LayerMask.NameToLayer("UI")
开启第5层和第六层
LayerMask mask=1<<5|1<<6
给相机添加渲染层
Component<Camera>().cullingMask |= 1 << 5
给相机移除渲染层
Component<Camera>().cullingMask &= ~(1 << 5)
相机只保留UI层
camera.cullingMask &= ~(1 << LayerMask.NameToLayer("UI"));
开关UI层,如果是开的则关,如果是关的则开
camera.cullingMask ^= 1 << LayerMask.NameToLayer("UI");
四:自定义一个像LayerMask的枚举
其实Unity中提供了Flags特性可以实现,将Flags标签特性定义在枚举类型上即可
这里我们使用PropertyDrawer重绘面板,自定义一个EnumFlags特性
using System;
using UnityEditor;
using UnityEngine;
public sealed class EnumFlagsAttribute : PropertyAttribute
{
public Type EnumType;
public EnumFlagsAttribute(Type enumType)
{
EnumType = enumType;
}
}
[CustomPropertyDrawer(typeof(EnumFlagsAttribute))]
public class EnumFlagsDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EnumFlagsAttribute target = attribute as EnumFlagsAttribute;
EditorGUI.BeginProperty(position, label, property);
if (property.propertyType == SerializedPropertyType.Enum)
{
var e = EditorGUI.EnumFlagsField(position, target.EnumType.Name, (Enum)Enum.ToObject(target.EnumType, property.intValue));
property.intValue = Convert.ToInt32(e);
}
EditorGUI.EndProperty();
}
}
定义一个枚举类型,枚举类型的值,添加
using UnityEngine;
using System;
public enum ELevel
{
Level1 = 1 << 0,
Level2 = 1 << 1,
Level3 = 1 << 2,
Level4 = 1 << 3,
}
public class Test : MonoBehaviour
{
[EnumFlags(typeof(ELevel))]
public ELevel level;
public void Start()
{
//添加某个选项
level |= ELevel.Level1;
//移除某个选项
level &= ~ELevel.Level1;
//判断是否包含某个值
if ((level & ELevel.Level1) != 0)
{
Debug.Log("被选中");
}
else
{
Debug.Log("没有被选中");
}
//判断是否包含某个值
if ((level & ELevel.Level1) == ELevel.Level1)
{
Debug.Log("被选中");
}
else
{
Debug.Log("没有被选中");
}
//判断是否包含某个值
bool contain = level.HasFlag(ELevel.Level1);
}
}
它的内部是这样实现的,例如如上定义的枚举,初始化时选的是Level1(0001),当选择Level3时,0001|0011=0011,之后将0011和每一个枚举值进行&操作,如果结果等于被比较的枚举值本身,那么这个值就是被选中的
五:编辑器中的Layer
选择Unity菜单栏的Layers,出现一个下拉栏
这里标示出了显示在Scene视图物体的Layer
例如将Default层的小眼睛图标闭上,Scene视图中则不会显示Layer为Default的物体
例如将Default层的锁给锁上,在Scene视图中则不能对Layer为Default的物体进行任何操作