【Unity】Tag、Layer、LayerMask

news2024/9/23 5:23:47

文章目录

  • 层(Layer)
    • 什么是Layer
    • Layer的应用场景
    • Layer层的配置(Tags & Layers)
    • Layer的数据结构
    • LayerMask
    • Layer的选中和忽略
    • Layer的管理(架构思路)
    • 层碰撞矩阵设置(Layer Collision Matrix)
    • 层排序(Sorting Layers)
      • 设置2D物体的Sorting Layer
      • 设置2D物体的Order In Layer
  • 标签(Tag)
    • Tag标签的配置
    • 给物体设置标签
    • Tag的基本用法
      • 获取场景中的物体
      • 判断物体是否具有某个Tag
    • Tag标签的应用场景


层(Layer)

什么是Layer

在Unity中,Layer的核心作用其实就是给游戏对象分类,这样我们就可以针对这些类别进行统一处理。比如我正在做一个Moba游戏,需要一个小地图,我打算用一个相机从地图上方俯视,这时候我需要在地图中显示一些标记(比如玩家的标记,怪物的标记)在地图上,这些标记是跟着玩家移动的,但是我的主相机中又不想看到这些标记,这时候就可以把这些标记指定为一个特殊的层,比如 “MapSignal” ,然后我们将主相机设置为不看 “MapSignal” 层,我们的功能就实现了。反之,我们可以在地图相机上,将玩家的Layer去掉,只保留 “MapSignal” 层,这样地图相机就不会显示玩家模型了。

Layer的应用场景

刚才举的例子只是 Layer 的一种用法,实际上 Layer 还有很多种作用,具体如下:

  1. 在 Scene 视图中隐藏某些 Layer ,可以在Scene视图工具栏中选择Layers,通过设置哪些Layer将出现在Scene视图中,以及哪些Laver不会出现;
  2. 排除不被灯光照亮的 Layer ,在创建自定义的用户界面、阴影系统或者使用复杂的光照系统时,可以选择灯光对象,然后在对应的Inspector视图中点击Culling Mask属性,取消选择你想忽略的那些Layer;
  3. 用于物理交互。在 Edit => ProiectSetings => Physics 菜单中,可以找到Layer Colision Matrix属性,用它来设置哪些游戏对象之间可以进行物理交互
  4. 用于射线检测的 Layer 。在某些情况下,可以使用 Layer 来忽略一些 Collider或Collision,比如在做射线检测时;
  5. 通过名称获取 Layer ,并 “开启 / 关闭” Layer ,可以通过 LayerMask.NameToLayer 方法获取特定的 Layer ,例如:int layer = LaverMask NameToLayer("Enemy");,然后可以使用1左移位运算符开启并获取Enemy Layer层,或者使用0左移位运算符关闭并获取Enemy Layer层。

Layer层的配置(Tags & Layers)

Unity中有一个用于设置标签(Tag)和层(Layer)的面板叫做 “Tags & Layers” ,打开方式很简单,只要选定场景中的任意对象,然后在Inspector面板中点击 Layer => Add Layer 即可。也可以在主菜单中点击 Edit => Project Settings,然后选择 Tags and Layers 标签页。
在这里插入图片描述
在这里插入图片描述

Layer的数据结构

Layer 数据其实是一个 int 值,每个 Layer 都是一个 int 值,且该值是 2 的 N 次方,看到这里相信有经验的人都知道是二进制的计算方法,由于 int32 是一个 32 位的二进制数,所以 Unity 的层也就设置了 32 个(0 ~ 31),所以每个层对应的数值就是 2 的 0 ~ N 次方,比如第 0 个 Layer 对应的值是 1,第 8 个 Layer 对应的值是 256 ,第十个 Layer 则是 1024。那么假如我给定一个数是 257 ,就代表了我同时拥有第 0 层( 2的0次方 = 1 )和第 8 层( 2的8次方 = 256 ),如下图,Layer0(Default)对应的int值就是2的0次方 = 1,而Layer7(Player)对应的就是2的7次方 = 128。当我们想要同时指定多个层时,就可以使用一个int值来表达。
在这里插入图片描述

LayerMask

LayerMask可以用来指定一个范围,以帮助检测物体是否在范围内,或设置射线是否会打到某个范围的层上。以射线为例:

// 指定第八层和第九层
int layers = (1 << 8) | (1 << 9);
// 入射射线
var ray = new Ray(startPoint, inDircection);
// 射线只会检测第八层和第九层的物体
var hits = new List<RaycastHit>(Physics.RaycastAll(ray, distance, layers));

在上面的案例中,射线只会检测第八层和第九层的物体,这样不但提高了运行效率,还使代码逻辑更为简洁,不需要手动判断物体类型。

Layer的选中和忽略

在代码中使用 | 可以使多个层联系在一起,使用 ~ 则会将指定的层排除掉,如下图:
在这里插入图片描述

Layer的管理(架构思路)

由于不确定在什么样的时候有可能会修改Layer的名称,所以不建议在代码中直接写入大量的Layer名称,所以通常要搞一个层的维护类,将层的名字做成常量,并提供更便捷的访问方式,代码如下:

using UnityEngine;

namespace Battle.Logic.LayerMasks
{
    /// <summary>
    ///     层管理器
    ///     所有层Layer相关的操作都应该在此类中完成
    ///     <para>
    ///         <Author>开发者 : Genesis (*╹▽╹*) </Author>
    ///     </para>
    /// </summary>
    public static class LayerMaskManager
    {
        /// <summary>
        ///     地面层
        /// </summary>
        private const string LayerGround = "Ground";

        /// <summary>
        ///     可触发的草
        ///     玩家进入草丛后可以隐身
        /// </summary>
        private const string LayerTriggerGrass = "TriggerGrass";

        /// <summary>
        ///     可触发的水
        ///     玩家进入水后可能被减速甚至被淹死
        /// </summary>
        private const string LayerTriggerWater = "TriggerWater";

        /// <summary>
        ///     可触发层
        ///     通常是有触发器的碰撞体才会在这一层
        /// </summary>
        private const string LayerCanTrigger = "CanTrigger";

        /// <summary>
        ///     可碰撞层
        ///     通常是可以影响玩家位置的碰撞体才会在这一层
        /// </summary>
        private const string LayerCanCollide = "CanCollide";

        /// <summary>
        ///     逻辑玩家层
        /// </summary>
        private const string LayerLogicPlayer = "LogicPlayer";

        /// <summary>
        ///     显示玩家层
        /// </summary>
        private const string LayerDisplayPlayer = "DisplayPlayer";

        /// <summary>
        ///     玩家是否接触地面的层遮罩
        /// </summary>
        public static LayerMask PlayerOnGroundLayerMask = LayerMask.GetMask(layerNames: new[] { LayerGround, LayerCanCollide });

        /// <summary>
        ///     玩家投棉球瞄准线的Layer遮罩
        /// </summary>
        public static LayerMask PlayerAimLayerMask = LayerMask.GetMask(layerNames: new[] { LayerGround, LayerCanCollide });

        /// <summary>
        ///     玩家投棉球子弹的Layer遮罩
        /// </summary>
        public static LayerMask CottonBulletLayerMask = LayerMask.GetMask(layerNames: new[] { LayerGround, LayerCanCollide });

        /// <summary>
        ///     摆放炮台环节显示的Layer遮罩
        /// </summary>
        public static LayerMask DefensePutLayerMask =
            LayerMask.GetMask(layerNames: new[] { LayerGround, LayerTriggerGrass, LayerTriggerWater, LayerCanCollide });


        /// <summary>
        /// 判断obj是否在layerMask中
        /// </summary>
        /// <param name="obj">需要验证的物体</param>
        /// <param name="layerMask">指定的层</param>
        /// <returns>物体是否在指定的层中</returns>
        public static bool IsInLayerMask(GameObject obj, LayerMask layerMask)
        {
            // 根据Layer数值进行移位获得用于运算的Mask值
            var objLayerMask = 1 << obj.layer;
            return (layerMask.value & objLayerMask) > 0;
        }

        /// <summary>
        /// 判断objMask是否在layerMask中
        /// </summary>
        /// <param name="objMask">需要验证的物体的层</param>
        /// <param name="layerMask">指定的层</param>
        /// <returns>该物体的层是否在指定的层中</returns>
        public static bool IsInLayerMask(LayerMask objMask, LayerMask layerMask)
        {
            // 根据Layer数值进行移位获得用于运算的Mask值
            var objLayerMask = 1 << objMask;
            return (layerMask.value & objLayerMask) > 0;
        }
    }
}

在上面的代码中,我将项目中层的名称定义为常量,后续使用层的名称时只允许使用常量,不允许直接使用字符串形式的LayerName,这样一旦层的名称有改动只需要改动此常量即可。
然后又提供了一些常用的已经绑定好的LayerMask(例如:PlayerAimLayerMask),便于在代码中直接使用,使用代码如下:

// 入射射线
var ray = new Ray(startPoint, inDircection);
// 获取射线经过的点(这里对层进行了过滤)
var hits = new List<RaycastHit>(Physics.RaycastAll(ray, distance, LayerMaskManager.PlayerAimLayerMask));

层碰撞矩阵设置(Layer Collision Matrix)

Unity支持通过设置决定层与层之间的碰撞关系,如下图:
在这里插入图片描述
物理引擎在检测碰撞时会通过Layer Collision Matrix的设置内容来决定要针对哪些层做碰撞监测,勾选的层之间碰撞有监测,没有勾选的层之间完全不会产生任何碰撞。

层排序(Sorting Layers)

Sorting Layers的主要作用是用于改变2D物体的渲染顺序,在 Hierarchy 中创建的 Canvas,Unity 默认自上而下渲染,位置越靠后的 Canvas 将渲染在靠前位置的 Canvas 之上,但有时我们需要让位置后靠后的Canvas先进行渲染或者让位置靠前的Canvas后渲染,此时就要用到Sorting Layer。
在这里插入图片描述
如上图,越往上的层级渲染顺序越靠前,也就是说下面层级的物体会显示在更上面一些。

设置2D物体的Sorting Layer

在Sprite Renderer组件中有一个Additional Settings节点,下面可以设置与层相关的功能。想要物体显示的靠前,就设置相对较高的层级即可。
在这里插入图片描述

设置2D物体的Order In Layer

有时候在同一Sorting Layer下也要区分物体的渲染顺序,这时候就需要用到Order In Layer设置,跟Sorting Layer差不多,数值越大,渲染越靠前。

标签(Tag)

由于Layer的数据结构相对简单,类似简单的树状结构,在某些复杂条件下可能无法满足开发需求。所以,Unity在层之外还做了一个Tag(标签)功能,每个物体都可以设置相应的Layer和Tag,通过Tag就将简单的树形结构改成了网状结构,例如:同一个层的物体可以又有标签A又有标签B,这样做的好处是可以实现跨层对某类物体进行判定筛选。

标签有助于识别游戏对象以便于编写脚本。通过使用标签,不需要使用拖放方式手动将游戏对象添加到脚本的公开属性,因此可以节省在多个游戏对象中使用相同脚本代码的时间。

Tag标签的配置

Tag标签的配置和Layer在同一个功能页中,面板图示如下:
在这里插入图片描述
最上面的Tags就是用于设置标签的。

给物体设置标签

选中物体后,Inspector面板左上角会有一个Tag下拉菜单,可以用来设置物体的Tag。
在这里插入图片描述

Tag的基本用法

获取场景中的物体

Unity支持通过标签获取场景中的物体,代码如下:

// 获取场景中的标签为MyTag01的所有游戏对象
GameObject.FindGameObjectsWithTag("MyTag01")
// 获取具有MyTag01标签的第一个GameObject
GameObject.FindWithTag("MyTag01");

我们可以通过这种方式获取场景中的某一类别的物体,且不受层级Layer影响。

判断物体是否具有某个Tag

判断物体是否具有某个Tag可以使用**gameObject.CompareTag(string)**函数,代码如下:

void Update()
{
    // 假设你想检查这个GameObject是否有Tag为"Player"
    if (gameObject.CompareTag("Player"))
    {
        // 如果是玩家,执行相关逻辑
        Debug.Log("This is the player.");
    }
}

Tag标签的应用场景

标签 (Tag) 是可分配给一个或多个游戏对象的参考词。例如,可为玩家控制的角色定义“Player”标签,并为非玩家控制的角色定义“Enemy”标签。还可以使用“Collectable”标签定义玩家可在场景中收集的物品。

标签对碰撞体控制脚本中的触发器很有用;例如,需要通过标签确定玩家是否与敌人、道具或可收集物进行交互。


更多内容请查看总目录【Unity】Unity学习笔记目录整理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1502921.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动化测试框架(全)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 无论是在自动化测试实践&#xff0c;还是日常交流中&#xff0c;经常听到一个词&#xff1a;框架…

java日志-干货系列-拒绝长篇大论

一、java日志系统架构图 二、架构图解释 日志框架&#xff1a;日志框架相较于门面是先出现的&#xff0c;因此日志框架本身就可以单独使用的&#xff0c;并不需要日志门面。 日志门面&#xff1a;简单点说就是统一了操作日志的api&#xff0c;然应用层无需关心底层的日志框架…

基于Java的物管系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术介绍 3 1.1 JSP介绍 3 1.2 MySQL介绍 3 1.3 B/S开发模式 3 1.4 Java介绍 4 2 系统分析 5 2.1 可行性研究 5 2.1.1技术可行性 5 2.2.2经济可行性 5 2.3.1操作可行性 5 2.2 需求分析 6 2.2.1系统用例图 6 2.2.2系统功能模块需求分析…

什么是微隔离技术?

微隔离产生的背景 首先来看下南北向流量以及东西向流量的含义 南北向流量 指通过网关进出数据中心的流量&#xff0c;在云计算数据中心&#xff0c;处于用户业务虚拟机&#xff08;容器&#xff09;跟外部网络之间的流量&#xff0c;一般来说防火墙等安全设备部署在数…

基于Springboot的智慧社区居家养老健康管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的智慧社区居家养老健康管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;…

问题:前端获取long型数值精度丢失,后面几位都为0

文章目录 问题分析解决 问题 通过接口获取到的数据和 Postman 获取到的数据不一样&#xff0c;仔细看 data 的第17位之后 分析 该字段类型是long类型问题&#xff1a;前端接收到数据后&#xff0c;发现精度丢失&#xff0c;当返回的结果超过17位的时候&#xff0c;后面的全…

智能警用装备柜管理系统|智能化可视化管理

我司&#xff08;JIONCH集驰&#xff09;警用装备管理系统&#xff08;智装备DW-S304&#xff09;是依托互云计算、大数据、RFID技术、数据库技术、AI、视频分析技术对警用装备进行统一管理、分析的信息化、智能化、规范化的系统。 智能警用装备柜是由普通储物柜的升级上应运而…

uniapp小程序获取位置

uni-app微信小程序uni.getLocation获取位置&#xff1b;authorize scope.userLocation需要在app.json中声明permission&#xff1b;小程序用户拒绝授权后重新授权-CSDN博客

产品推荐 - 基于6U VPX的双TMS320C6678+Xilinx FPGA K7 XC7K420T的图像信号处理板

综合图像处理硬件平台包括图像信号处理板2块&#xff0c;视频处理板1块&#xff0c;主控板1块&#xff0c;电源板1块&#xff0c;VPX背板1块。 一、板卡概述 图像信号处理板包括2片TI 多核DSP处理器-TMS320C6678&#xff0c;1片Xilinx FPGA XC7K420T-1FFG1156&#xff0c;1片…

LeetCode 654.最大二叉树

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回 nums 构建的 最大二叉树…

付强:基于注意力机制的听觉前端处理 | 嘉宾公布

一、智能家居与会议系统专题论坛 智能家居与会议系统专题论坛将于3月28日同期举办&#xff01; 智能会议系统它通过先进的技术手段&#xff0c;提高了会议效率&#xff0c;降低了沟通成本&#xff0c;提升了参会者的会议体验。对于现代企业、政府机构和学术界是不可或缺的。在这…

静态时序分析:SDC约束命令set_disable_timing详解

静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html 目录 指定对象列表 指定源、目的引脚 指定恢复 简单使用 写在最后 上一章中&#xff0c;我们学习了如何使用set_case_analysis模式分析命令&#xff0c;它通过指定某个端口或引脚为固定值&…

国产硅片膜厚检测仪

硅片膜厚检测仪是半导体行业中一种至关重要的设备&#xff0c;用于精确测量硅片上薄膜的厚度。在半导体制造工艺中&#xff0c;薄膜厚度的控制对于保证器件性能和可靠性具有决定性的作用。因此&#xff0c;硅片膜厚检测仪的研发和应用对于推动半导体技术的发展具有重要意义。 一…

登录校验认证

会话技术 会话&#xff1a;用户打开浏览器&#xff0c;访问web服务器的资源&#xff0c;会话建立&#xff0c;直到有一方断开连接&#xff0c;会话结束。在一次会话中可以包含多次请求和响应。 会话跟踪&#xff1a; 一种维护浏览器状态的方法&#xff0c;服务器需要识别多次请…

Scalable Diffusion Models with Transformers(DiTs)论文阅读 -- 文生视频Sora模型基础结构DiT

nlpcver 忠于理想 ​关注他 106 人赞同了该文章 文章地址&#xff1a;Scalable Diffusion Models with Transformers 简介 文章提出使用Transformers替换扩散模型中U-Net主干网络&#xff0c;分析发现&#xff0c;这种Diffusion Transformers&#xff08;DiTs&#xff09…

市域社会治理现代化指挥中心项目方案

1.4.1专题分析应用建设要求 1.4.1.1总体要求 系统根据各专题实际业务需求提供详细的指标体系清单&#xff0c;同时应根据指标体系提供设计各专题应用的原型效果图&#xff1b;围绕党建引领、基层治理、城市管理、公共服务、公共安全多方面进行分析展示核心数据&#xff0c;体…

AI跟踪报道第32期-新加坡内哥谈技术-本周AI新闻:超越GPT4的Claude

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

删除网络连接不存在的网络驱动器

目录预览 一、问题描述二、解决方案三、参考链接 一、问题描述 虚拟机之前连接了主机&#xff0c; 二、解决方案 方法一&#xff1a;从文件资源管理器断开 Windows 10 上映射的网络驱动器&#xff0c; 在 Windows 10 上打开文件资源管理器。 从左窗格中单击此 PC 。 在“网络…

Linux系统架构----nginx的访问控制

nginx的访问控制 一、nginx基于授权的访问控制概述 Nginx与Apache一样&#xff0c;可以实现基于用户权限的访问控制&#xff0c;当客户端想要访问相应的网站或者目录时&#xff0c;要求用户输入用户名和密码&#xff0c;才能正常访问配置步骤生成用户密码认证文件 &#xff1…

若依/RuoYi-Vue使用docker-compose部署

系统需求 JDK > 1.8 MySQL > 5.7 Maven > 3.0 Node > 12 Redis > 3 思路 前端服务器 nginx 后端服务器代码打包 java、maven、node 数据库/缓存 mysql、redis 开始 创建目录ruoyi并进入 克隆若依代码 git clone RuoYi-Vue: &#x1f389; 基于Spring…