Tag & Layer
Tag는 스크립트 식별용 라벨(CompareTag)이고 Layer는 Physics 충돌·Camera culling·Raycast LayerMask용 그룹입니다. Tags and Layers·Collision Matrix·GetMask 설정을 배우는 실무 입문 가이드입니다.
상상해 보세요...
Tag는 이름표와 같습니다——"Player", "Enemy", "Treasure"——경비원이 즉시 알아보고 반응(CompareTag)합니다. Layer는 건물의 구역 도면처럼——허가된 층만 들어가고(Camera Culling Mask), 어느 방이 물리적으로 상호작용할지 정합니다(Physics Layer Collision Matrix).
개념 자세히
Tag는 GameObject의 문자열 라벨입니다(GO당 하나).
문자열 할당을 피하려면 gameObject.tag == “Player”보다
gameObject.CompareTag(“Player”)를 쓰세요. 내장 태그:
Untagged, Respawn, Finish, EditorOnly, MainCamera, Player, GameController.
Layer는 정수 0–31(최대 32개)입니다. 각 Layer는 LayerMask(32비트 비트마스크)의 한 비트입니다. Layer가 담당: (1) Camera Culling Mask — 선택한 Layer만 렌더; (2) Physics Layer Collision Matrix — 어느 Layer가 충돌할지; (3) Raycasting LayerMask — 레이가 맞힐 Layer.
LayerMask:
LayerMask.GetMask(“Enemy”, “NPC”)로 합칩니다. ~로
반전(제외): ~LayerMask.GetMask(“Player”) = Player를 뺀 모든 레이어.
좋은 습관: Layer 이름은 역할 기준(객체 이름 X), Edit → Project Settings → Tags and Layers에서 만듭니다. 예: Ground, Projectile, Interactable, UI, PostProcess.
비교: Tag vs Layer
🏷 Tag
목적
스크립트에서 객체 유형 식별 (CompareTag)
수량
무제한(문자열); GO마다 Tag 1개
용도
OnTriggerEnter, FindWithTag, 스크립트 비교
예시
📚 Layer
목적
Physics와 Camera 렌더링을 위한 객체 그룹
수량
최대 32개 레이어(0–7 Unity 예약), 비트 0–31
용도
Culling Mask, Collision Matrix, Raycast LayerMask
예시
실습 단계
새 Tag/Layer 만들기
Edit → Project Settings → Tags and Layers. Tags 또는 Layers 목록에 항목을 추가합니다.
GameObject에 할당
Hierarchy에서 GO 선택 → Inspector 상단 Tag 또는 Layer 드롭다운.
Collision Matrix 구성
Edit → Project Settings → Physics → Layer Collision Matrix → 충돌하지 않을 쌍의 체크 해제.
Camera Culling Mask 설정
Camera 선택 → Inspector → Culling Mask → 렌더할 Layer 선택(UI Camera는 보통 UI만).
Raycast에서 LayerMask 사용
Physics.Raycast(origin, dir, distance, LayerMask.GetMask("Ground")) — Ground만 맞춤.
인터랙티브 시뮬레이터
GameObject를 클릭해 선택하세요. Tag와 Layer를 바꾸고 Collision Matrix와 Raycast를 시험해 보세요.
Hierarchy
GameObject를 선택하세요
코드 예제
기본OnTriggerEnter 안에서 Tag로 객체를 식별합니다.
using UnityEngine;
public class TreasureChest : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
// CompareTag does not allocate a string — better than ==
if (other.CompareTag("Player"))
{
Debug.Log("Player collected the treasure chest!");
gameObject.SetActive(false);
}
}
}
// Find every Enemy in the scene by Tag
GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
foreach (var e in enemies) e.GetComponent<EnemyAI>().Alert();코드 예제
고급Raycast의 LayerMask와 런타임 Layer 변경.
using UnityEngine;
public class PlayerGroundCheck : MonoBehaviour
{
[SerializeField] private float checkDistance = 0.1f;
// Build LayerMask from names — cache it, do not rebuild every frame
private readonly int _groundMask = LayerMask.GetMask("Ground", "Platform");
public bool IsGrounded =>
Physics.Raycast(transform.position, Vector3.down, checkDistance, _groundMask);
void Update()
{
if (IsGrounded)
GetComponent<Rigidbody>().drag = 5f; // friction while grounded
else
GetComponent<Rigidbody>().drag = 0f; // no drag in the air
}
// Change Layer at runtime (e.g. ghost through walls)
public void SetGhostMode(bool ghost)
{
gameObject.layer = LayerMask.NameToLayer(ghost ? "Ghost" : "Player");
}
}📌 빠른 정리
- ▸Tag = 스크립트에서 식별; Layer = Physics와 Camera 제어
- ▸GC 할당을 피하려면
tag ==보다CompareTag() - ▸LayerMask는 비트마스크——매직 넘버 대신
GetMask() - ▸최대 32 Layer; 불필요한 Collision Matrix 쌍은 체크 해제
⚠️ 흔한 실수
❌ gameObject.tag == "Player" 사용
호출마다 문자열 할당 → GC 압력
✅ gameObject.CompareTag("Player")
❌ 하드코딩 레이어 비트: layerMask = 8
레이어 순서가 바뀌면 깨짐
✅ LayerMask.GetMask("Ground")