Today I Learn

25/04/29 | TIL RayCast 재정의하기

오늘도즐겨 2025. 4. 29. 23:34

오류 카메라가 바닥과 맞닿아 있어 그라운드 랜더링 이상현상

 

강의 중간에 CameraContainer 오브젝트를 생성 후, Y 위치값을 지정해 주었는데, 

나는 기본 0으로 되어있어 카메라가 바닥과 맞닿아있었다.

카메라는 Position값을 (0,0,0)으로 세팅하고, CameraContainer의 Position값을 (0,1.7,0)

 

개인 프로젝트를 하면서 강의 내용을 참고하며 1인칭과 3인칭을 오가는 Camera를 만들었었는데,

그땐 카메라가 플레이어의 오브젝트의 몸속이 보이는 오류가 있었지만, 큰 문제는 아닌 것 같아 넘어갔었는데

 

최종프로젝트를 진행하면서 해결 방법을 알게 되었다!!!!!!

- Clipping Planes - Near 값을 기본 0.3에서 조금 더 적당한 값으로 늘려주면 완성!

1인칭 은 플레이어가 보이지 않아야 하지만, 정확한 플레이어의 위치에 있어야 하기에!

코드로 제외하는 건 나중에 무기 오브젝트가 보이도록 하는 카메라를 생성하고 제어하는 것이 있기에 그때 다시 분석해 보기로 한다! 


다른 것보다 오늘 가장 완벽하게 알고 가고 싶은 내용은 바로 Raycast이다.

보통 내가 활용하는 방식은 RaycastHit로 바닥을 체크하는 것과

적이 플레이어를 추적할 거리 정도로 알고 있는데, 다른 방법은 무엇이 있을지

 

 

Raycast는 다양하게 활용할 수 있는데, 

Ray - 직선의 시작점(origin)과 방향(direction)

Ray ray = new Ray(transform.position, transform.forward); // 오브젝트

Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0)); // 카메라 중심

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 마우스

 

Raycast - 눈에 보이지 않는 광선(Ray)에 맞은 물체가 무엇인지 여부를 판단한 뒤 여러 가지 후처리를 하는 방식.

Ray, RaycastHit, MaxDistance, LayerMask 등의 옵션

 

RaycastHit - Raycast에 의해 검출된 객체의 정보가 담겨있다.

RaycastHit.point - 레이캐스팅이 감지된 위치

RaycastHit.distance - Ray의 원점에서 충돌 지점까지의 거리

RaycastHit.transform - 충돌 객체의 transform에 대한 참조

 

Physics.Raycast()는 처리 우선순위가 충돌체 콜라이더 기준임


강의에서 Ray를 활용 한 예시에서의 의문

public LayerMask groundLayerMask;

LayerMask를 통해 Inspector에서 Player 빼고 모든 레이어를 포함시켜 줌

bool IsGrounded()
{
    Ray[] rays = new Ray[4]
    {
        new Ray(transform.position + (transform.forward * 0.2f) + (transform.up * 0.01f), Vector3.down),
        new Ray(transform.position + (-transform.forward * 0.2f) + (transform.up * 0.01f), Vector3.down),
        new Ray(transform.position + (transform.right * 0.2f) + (transform.up * 0.01f), Vector3.down),
        new Ray(transform.position + (-transform.right * 0.2f) + (transform.up * 0.01f), Vector3.down)
    };
    for (int i = 0; i < rays.Length; i++)
    {
        if (Physics.Raycast(rays[i], 0.1f, groundLayerMask))
        {
            return true;
        }
    }
    return false;
}

플레이어의 4개에 임의의 다리를 만들어주고 충돌을 감지하게 함.

기본 위치를 정해주고, 방향을 아래로 쏴준다. (origin, direction)

 

여기서 Ray를 배열로 만든 이유가 궁금했다.

단순히 시작점과 방향만을 저장하는 구조체인데, 왜 바로 감지하지 않았는지?

 

1. 시작점/방향을 미리 계산해서 반복문 내 중복 계산 방지

2. 4개를 만듦으로써 여러 방향에서 감지해 정확도 향상

3. RaycastHit 미사용 = 충돌여부를 (True/False)만 판단하면 충분하므로 Hit정보가 필요 없음!


사실 여기서 기초가 없는 나는 뭐가 다른 지 모르겠다.

Ray와 Raycast, RaycastHit의 차이를!!!!!!!

 

위의 정리된 내용들을 봐도 모르겠다.

그래서 간단히 알아보자면,

 

Ray = 활을 당긴 방향과 위치 (아직 안 쐈음)

그냥 방향을 가지고 있는 데이터 객체일 뿐이다.

방향성과 시작점을 가진 단순 광선 (데이터)

 

Raycast = 실제로 화살을 날리는 동작
→ 그리고 무엇에 맞았는지 검사

Ray를 실제로 쏘는 함수 (충돌 검사 실행) 

 

RaycastHit = 단순히 충돌 여부만 확인하는 bool 결과보다

훨씬 더 많은 충돌 정보를 담고 있는 구조체

 

💡RaycastHit가 담고 있는 정보들

point 충돌 지점 (Vector3)
normal 충돌 면의 법선 벡터
distance 레이 시작점부터 충돌 지점까지 거리
collider 충돌한 콜라이더 객체
transform 충돌한 오브젝트의 Transform
rigidbody 충돌한 오브젝트의 Rigidbody (있다면)
textureCoord 충돌한 텍스처의 UV 좌표
triangleIndex 충돌한 메시의 삼각형 인덱스 (MeshCollider에 한함)

 

✅ 언제 RaycastHit를 쓰는가?

충돌 지점 좌표가 필요한 경우 - ex. 총알이 맞은 위치, 이펙트 위치 지정

충돌한 오브젝트를 알고 싶은 경우 - ex. 적 감지, 상호작용 대상 확인

표면 방향(법선)을 알고 싶은 경우 - ex. 벽에 붙이기, 반사 계산 등

충돌 메시 정보를 활용할 때  - ex. 데칼, 피격 이펙트, 텍스처 페인팅

 

✅ Ray만 사용하는 경우는?

단순히 "무언가 있나? 없음?"만 판단할 때 (빠름)

성능이 중요한 대규모 바닥 체크, 내비게이션 검사 등에서 자주 씀