Trigger
Trigger는 물리 반발 없이 Enter·Stay·Exit만 감지하는 Collider입니다. 체크포인트·픽업·자동문·피해 구역에 쓰이며, 한쪽에는 Rigidbody가 필요합니다. OnTriggerEnter와 Layer·Tag 필터로 깔끔한 구역 감지 흐름을 배우는 가이드입니다.
상상해 보세요...
Trigger는 슈퍼마켓 자동문 센서와 같습니다. 문에 들어가도 밀어내지 않고 알아채기만 한 뒤 열립니다. 물리 힘 없이 “누군가 들어왔다”는 신호만 있습니다. Unity의 `OnTriggerEnter`가 그 신호 — 캐릭터가 구역에 닿는 순간 문 열기·힐·컷신 등에 씁니다.
개념 자세히
Trigger는 Is Trigger 체크가 켜진 일반 Collider입니다. 켜면
통과형 — 몸이 지나가도 밀어내지 않습니다. 대신 Unity가 세 콜백을 호출합니다:
OnTriggerEnter(진입), OnTriggerStay
(안에 있는 동안 매 프레임), OnTriggerExit(이탈).
Trigger가 발동하려면 둘 중 적어도 하나에
Rigidbody가 있어야 합니다. 흔한 실수 — Rigidbody 없는 정적 두 개는
서로를 트리거하지 않습니다. 중력이 필요 없으면
isKinematic = true로 둡니다.
활용 범위가 넓습니다: checkpoint(통과 시 저장), pickup zone(아이템 수집), enemy detection(AI 감지 반경), damage zone(불·산), cutscene trigger(스토리 비트). 진짜 물리 없이 “누가 이 볼륨에 들어왔나?”만 필요합니다.
Unity 2D에서는 OnTriggerEnter2D,
OnTriggerStay2D, OnTriggerExit2D — 형태는 같고 인자가
Collider 대신 Collider2D입니다.
Trigger vs Collision 라이프사이클
Trigger (isTrigger = true)
OnTriggerEnter
접촉한 첫 프레임
OnTriggerStay
안에 있는 동안 매 프레임
OnTriggerExit
나갈 때 마지막 프레임
✅ 통과 가능 — 반력 없음
Collision (isTrigger = false)
OnCollisionEnter
충돌한 첫 프레임
OnCollisionStay
닿아 있는 동안 매 프레임
OnCollisionExit
떨어질 때
🔒 막힘 — 물리 반력이 있음
⚠️ 필수 조건:
두 오브젝트 중 적어도 하나에 Rigidbody(또는 Rigidbody2D)가 있어야 trigger/collision이 동작합니다.
실습 단계
Trigger 볼륨 만들기
빈 GameObject를 만들고 Add Component → BoxCollider, "Is Trigger"를 켭니다. 원하는 구역 크기로 맞춥니다.
움직이는 몸에 Rigidbody
캐릭터나 발사체에는 Rigidbody가 필요합니다. 중력이 싫으면 isKinematic = true.
Trigger 핸들러 작성
trigger 오브젝트 또는 움직이는 몸에 OnTriggerEnter(Collider other) 스크립트를 추가합니다.
Layer로 필터
other.gameObject.layer 또는 CompareTag로 관심 있는 오브젝트만 반응하게 합니다.
Gizmo 색으로 디버그
Trigger는 cyan(충돌은 green)으로 그려집니다. 추가 디버그가 필요하면 OnDrawGizmos를 씁니다.
인터랙티브 시뮬레이터
← → 화살표(또는 아래 버튼)로 캐릭터를 걸어 Trigger 구역을 통과해 보세요.
캐릭터를 트리거 영역으로 이동하세요...
코드 예제
기본간단한 픽업: 플레이어가 Trigger에 들어오면 코인을 수집합니다.
using UnityEngine;
// Attach this to a Coin with a Collider that has isTrigger = true
public class CoinPickup : MonoBehaviour
{
public int value = 10;
public AudioClip pickupSound;
void OnTriggerEnter(Collider other)
{
// Only react to the Player
if (!other.CompareTag("Player")) return;
// Award points via GameManager
GameManager.instance.AddScore(value);
// Play a pickup sound
AudioSource.PlayClipAtPoint(pickupSound, transform.position);
// Remove the coin from the scene
Destroy(gameObject);
}
}코드 예제
고급시간제 위험 구역: 안에 있는 동안 매 프레임 피해, 나가면 중단.
using UnityEngine;
using System.Collections;
// A fire zone that damages while you stand in the trigger
public class DamageZone : MonoBehaviour
{
public float damagePerSecond = 10f;
public LayerMask damageable;
Coroutine damageRoutine;
PlayerHealth currentTarget;
void OnTriggerEnter(Collider other)
{
if ((damageable.value & (1 << other.gameObject.layer)) == 0) return;
currentTarget = other.GetComponent<PlayerHealth>();
if (currentTarget != null)
damageRoutine = StartCoroutine(DamageLoop());
}
void OnTriggerExit(Collider other)
{
if (damageRoutine != null)
{
StopCoroutine(damageRoutine);
damageRoutine = null;
currentTarget = null;
}
}
IEnumerator DamageLoop()
{
while (true)
{
currentTarget.TakeDamage(damagePerSecond * Time.deltaTime);
yield return null; // Wait one frame
}
}
}📌 빠른 정리
- ▸isTrigger=true → 통과하며 이벤트 수신
- ▸적어도 한쪽에는 Rigidbody 필요
- ▸CompareTag()가 문자열 직접 비교보다 빠름
- ▸OnTriggerStay는 매 프레임 — 비용 주의
- ▸LayerMask로 저렴하게 필터
⚠️ 흔한 실수
❌ isTrigger가 켜져 있는데도 Trigger가 안 뜸
양쪽 모두 Rigidbody 없음
✅ 움직이는 몸에 Rigidbody 추가(필요 시 isKinematic=true)
❌ OnTriggerStay 안에서 Destroy(other.gameObject)
물리 루프 중간에 파괴되어 에러
✅ OnTriggerEnter에서 Destroy하고 null 체크