1. Layer 和 Tag 的共同点
在代码中,两者都能区分物体,用来过滤相应的物体,比如查找物体和射线检测过滤。
2. 不同点
- Tag(标签):给单个物体起一个标识名称,用于查找、判断身份;一个物体只能有 1 个 Tag。
- Layer(层):归类分组,用于渲染、射线检测、相机裁剪、物理碰撞过滤;一个物体只属于 1 个 Layer。
详细对比
1. Tag
用途:区分物体类型,代码快速识别对象
- 一个 GameObject仅有一个 Tag
- 内置默认:
Untagged、Respawn、Player、Enemy等,可以自定义
2. Layer
用途:分组过滤,控制渲染、射线、物理
- 总共最多 32 层(0~31),0 默认 Default,31 层推荐留给引擎
- 一个物体只能归属一层
- 核心使用场景:
- 相机 Culling Mask:只渲染指定层
- Raycast 射线检测掩码,只探测目标层
- Layer Collision Matrix:物理碰撞矩阵,控制哪些层互相碰撞
关键差异对照表
表格
| 特性 | Tag | Layer |
|---|---|---|
| 数量上限 | 自定义数量无硬性限制 | 最多 32 层 (0~31) |
| 归属规则 | 一物只能 1 个 Tag | 一物只能 1 个 Layer |
| 本质 | 字符串标记 | 数字索引 + 位掩码 |
| 射线筛选 | 不能直接过滤,只能检测到物体后再判断 tag | 射线可直接设置 LayerMask,提前过滤,性能更高 |
| 相机渲染控制 | 不支持 | CullingMask 直接控制是否渲染该层 |
| 物理碰撞过滤 | 不支持 | 碰撞矩阵基于 Layer 设置 |
| 典型场景 | 找玩家、区分敌人 / 道具身份 | UI 与场景分离、隐藏远景、射线只打敌人、碰撞分层 |
注意:
❌ 不要用 Layer 单纯替代 Tag 做身份判断(浪费层资源)
❌ 不要用 Tag 做射线过滤(射线全部命中后再判断 tag,性能差,大量物体时卡顿)
✅ 射线优先用 LayerMask 预先过滤,拿到物体后再用 Tag 精细区分。
在射线检测中
场景有 1000 个物体,50 个敌人。
方案 1:只用 Tag
射线不做任何筛选,遍历碰到所有物体(墙体、地面、道具全都能命中)
if(Physics.Raycast(ray,out hit)) { if(hit.collider.tag == "Enemy") // 命中之后代码判断 { } }坏处:大量无用碰撞检测,物体越多越卡。
方案 2:先用 Layer 过滤
射线带上 LayerMask,物理引擎直接忽略非 Enemy 层物体,根本不会返回
int layerMask = 1 << LayerMask.NameToLayer("Enemy"); if(Physics.Raycast(ray,out hit, 100, layerMask)) { // 能进来的一定是Enemy层,减少大量计算 }总结:
一、什么时候优先用 Layer
只要涉及引擎自带功能的筛选,一律 Layer!
相机不想渲染某一类物体(Culling Mask) 射线 / 球形检测,只想探测某一类物体 物理碰撞:A 层和 B 层不发生碰撞(Collision Matrix) 2D/3D 物理查询、OverlapSphere 等物理查询过滤
✅ 本质需求:在引擎底层就把不需要的物体拦截在外,提升性能
限制:全局最多 32 层,资源有限,不能随便新建。
二、什么时候优先用 Tag
场景:已经拿到物体了,需要精细区分身份,不涉及引擎底层过滤典型场景:
举例:所有怪物都放在 Enemy Layer(射线只打怪物),但是怪物分普通小怪、精英、Boss → Layer 统一归类,Tag 用来区分 Boss / 小怪
Layer:Enemy Tag:NormalEnemy / BossEnemyGameObject.FindWithTag("Player")快速找到玩家- 碰撞触发 OnTriggerEnter,碰到物体后判断:是道具还是敌人还是NPC?
- 同一 Layer 内,还要细分种类
即:
Layer 做大范围大类分组(粗筛选)UI、Player、Enemy、Projectile、Background、Item
Tag 在同一大类内部做细分(精细识别)