내일배움캠프 29일차 TIL
📌 Raycast
눈에 보이지 않는 직선(광선, Ray)을 쏴서, 그 선과 충돌한 Collider를 탐지하는 물리 기능
광선은 시작점(origin)과 방향(direction)으로 구성되며, 충돌하면 Collider, 거리, 충돌 지점, 방향 등을 알려준다.
Ray 구조
Unity에서 Ray는 어디에서 어느 방향으로 광선을 쏘는지를 나타내는 구조체이다.
public struct Ray
{
public Vector3 origin; // 시작 지점
public Vector3 direction; // 방향 (단위 벡터)
}
생성 방법
Ray ray = new Ray(Vector3 startPoint, Vector3 direction);
// 예시
Ray ray = new Ray(transform.position, transform.forward);
transform.forward는 오브젝트의 앞 방향을 나타내는 단위 벡터이다.
마우스 클릭한 지점에 Ray 쏘기
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Debug.Log("충돌한 오브젝트: " + hit.collider.name);
}
}
}
ScreenPointToRay()는 마우스 위치 (스크린 좌표)에서 월드 공간을 향해 레이 생성해주는 매우 유용한 메서드.
RaycastHit 구조
RaycastHit hit;
hit.point // 충돌 위치 (Vector3)
hit.normal // 충돌면의 법선 벡터
hit.distance // origin부터 충돌 지점까지의 거리
hit.collider // 충돌한 Collider
hit.transform // 충돌한 오브젝트의 Transform
hit.rigidbody // 연결된 Rigidbody (있을 경우)
Physics.Raycast 메서드 종류
Physics.Raycast()는 기본적으로 "광선을 쏘아 충돌 여부를 검사하고, 충돌 정보를 반환하는 메서드" 이다.
가장 일반적인 형태 (3D용)
bool Physics.Raycast(Ray ray, out RaycastHit hit, float maxDistance);
- 반환값: bool (충돌했는가?)
- 충돌 정보: RaycastHit
- 방향: Vector3
- 시작점: Vector3
- 레이어 필터링: LayerMask
- 트리거 포함 여부: QueryTriggerInteraction
대표적인 오버로드 버전 10가지
| 메서드 시그니처 | 설명 |
| bool Raycast(Vector3 origin, Vector3 direction) | 가장 간단한 형태. 충돌 여부만 반환. (Hit 정보 없음) |
| bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo) | 충돌 여부와 함께 충돌 정보를 반환 |
| bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance) | 최대 거리 제한 추가 |
| bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask) | 특정 레이어만 충돌 검사 |
| bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance, int layerMask, QueryTriggerInteraction queryTriggerInteraction) | 트리거 포함 여부까지 지정 가능 |
| bool Raycast(Ray ray) | Ray 객체 사용, Hit 정보 없음 |
| bool Raycast(Ray ray, out RaycastHit hitInfo) | Ray 객체 사용 + 충돌 정보 반환 |
| bool Raycast(Ray ray, float maxDistance) | Ray 객체 사용 + 거리 제한 |
| bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance) | Ray 객체 사용 + 거리 + 충돌 정보 |
| bool Raycast(Ray ray, out RaycastHit hitInfo, float maxDistance, int layerMask, QueryTriggerInteraction queryTriggerInteraction) | 모든 인자를 다 설정 가능 |
1. 단순 충돌 검사 (hit 정보 없음)
bool isHit = Physics.Raycast(transform.position, transform.forward);
2. 충돌 지점 정보 받기
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit))
{
Debug.Log("Hit object: " + hit.collider.name);
}
3. 거리 제한 추가
if (Physics.Raycast(transform.position, transform.forward, out hit, 10f))
{
Debug.Log("10미터 안에서 충돌!");
}
4. 레이어 마스크 사용
int layerMask = LayerMask.GetMask("Enemy");
if (Physics.Raycast(transform.position, transform.forward, out hit, 10f, layerMask))
{
Debug.Log("Enemy 레이어에 있는 대상에 충돌");
}
5. 트리거 포함 여부 설정
if (Physics.Raycast(transform.position, transform.forward, out hit, 10f, layerMask, QueryTriggerInteraction.Collide))
{
Debug.Log("트리거 포함해서 감지됨!");
}
QueryTriggerInteraction 옵션
| 값 | 의미 |
| UseGlobal | 기본 설정 따름 (Project Settings > Physics) |
| Ignore | 트리거 Collider 무시 |
| Collide | 트리거 Collider도 감지 |
언제 어떤 오버로드를 써야 할까?
| 상황 | 추천 메서드 |
| 단순히 무언가 있는지 확인만 할 때 | Raycast(origin, direction) |
| 충돌 위치, 거리, 대상이 필요할 때 | Raycast(origin, direction, out hit) |
| 거리 제한이 중요할 때 | Raycast(..., maxDistance) |
| 특정 레이어만 감지하고 싶을 때 | Raycast(..., layerMask) |
| 트리거 콜라이더도 포함하고 싶을 때 | Raycast(..., ..., ..., ..., QueryTriggerInteraction.Collide) |
| Ray 객체를 미리 만들고 재사용할 때 | Raycast(ray, ...) |
Raycast의 고급 기능
LayerMask
특정 레이어만 충돌을 감지하고 싶을 때
int layerMask = LayerMask.GetMask("Enemy", "Wall");
if (Physics.Raycast(transform.position, transform.forward, out hit, 10f, layerMask))
{
Debug.Log("적 또는 벽에 충돌!");
}
Ray 시각화 (디버깅)
Debug.DrawRay(transform.position, transform.forward * 10f, Color.red, 1f);
Scene 뷰에서 빨간 선이 1초 동안 그려져서 Ray 방향, 길이를 확인할 수 있다.
RaycastAll
기본 Raycast는 가장 가까운 하나만, RaycastAll은 광선 경로에 있는 모든 Collider를 반환한다.
RaycastHit[] hits = Physics.RaycastAll(transform.position, transform.forward, 10f);
foreach (var h in hits)
{
Debug.Log("충돌한 오브젝트: " + h.collider.name);
}
RaycastNonAlloc
성능 최적화
매번 배열을 새로 만들지 않고 미리 준비된 배열에 결과를 저장한다.
메모리 할당이 없어져서 가비지 컬렉션 (Garbage Collection; GC) 발생을 줄인다. (모바일, VR 등에서 유용)
RaycastHit[] results = new RaycastHit[10];
int hitCount = Physics.RaycastNonAlloc(transform.position, transform.forward, results);
for (int i = 0; i < hitCount; i++)
{
Debug.Log("감지된: " + results[i].collider.name);
}
Raycast vs RaycastAll vs RaycastNonAlloc
| 메서드 | 특징 |
| Physics.Raycast() | 가장 가까운 한 개만 반환 |
| Physics.RaycastAll() | 경로 상 모든 충돌체 반환 (배열 반환) |
| Physics.RaycastNonAlloc() | 미리 준비한 배열에 충돌체 정보 저장 (GC 없음) |
2D Raycast (Physics2D)
2D는 별도 API 사용!
Physics2D.Raycast()는 2D 물리 세계에서 선을 쏘아 충돌체를 감지하는 메서드이다.
2D 충돌체 (Collider2D)에만 반응 하며, 반환 값은 RaycastHit2D 구조체.
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 5f);
if (hit.collider != null)
{
Debug.Log("2D에서 바닥 감지됨: " + hit.collider.name);
}
Physics.Raycast와 Physics2D.Raycast는 완전히 별개임 주의!
유니티에서 Raycast 실전 활용 예시
| 용도 | 설명 | 예시 |
| 마우스 클릭 오브젝트 감지 | Camera.ScreenPointToRay() 사용 | UI가 아닌 월드 클릭 감지 |
| 벽/장애물 감지 | transform.forward으로 쏘기 | 플레이어 주변 체크 |
| 시야 판정 | 적 → 플레이어 방향으로 쏘기 | 플레이어가 가려져 있는지 확인 |
| 점프 가능 여부 | 발 아래로 쏘기 | "Grounded?" 체크 |
| 오브젝트 거리 감지 | hit.distance 사용 | 가까이 가면 이벤트 트리거 |

'TIL' 카테고리의 다른 글
| [Unity] ImageType (1) | 2025.05.21 |
|---|---|
| [Unity] 델리게이트 (Delegate) (1) | 2025.05.20 |
| 객체지향 설계의 5가지 원칙 - SOLID (0) | 2025.05.16 |
| Unity 협업 중 프리팹 충돌 및 .meta 파일 관련 트러블 슈팅 (1) | 2025.05.15 |
| 방 종류 추가와 문 생성 수정 (0) | 2025.05.12 |