Raycasting (광선 추적)

Raycasting은 광선을 쏴서 충돌 여부와 충돌 정보를 확인하는 기능입니다. 광선이 충돌하면 충돌 지점과 객체에 대한 정보를 반환하며, 이를 활용해 다양한 게임 로직을 구현할 수 있습니다.


Raycasting의 주요 특징

  1. 광선 발사:

    • 광선은 특정 시작점(Position)과 방향(Direction)을 기반으로 발사됩니다.
    • Physics.Raycast를 사용하면 특정 범위 내에서 충돌한 객체를 감지할 수 있습니다.
    • 충돌 여부는 bool 값으로 반환되며, 충돌한 객체의 정보는 RaycastHit 구조체에 저장됩니다.
  2. 충돌 정보:

    • 충돌한 객체의 Collider, Transform, Rigidbody, 위치(Position), 방향(Normalized Vector) 등을 확인할 수 있습니다.
    • 반환값은 충돌 객체 1개(Raycast) 또는 모든 충돌 객체 배열(RaycastAll)로 얻을 수 있습니다.
  3. Debug.DrawRay:

    • 광선의 시각적인 확인을 위해 사용합니다.
    • Debug 기능으로 실제 광선이 발사된 경로를 화면에 표시합니다.

Raycasting 사용 방법

1. 하나의 객체와 충돌 확인

Vector3 look = transform.TransformDirection(Vector3.forward); // 로컬 Forward를 월드 Forward로 변환
RaycastHit hit;

if (Physics.Raycast(transform.position + Vector3.up, look, out hit, 10))
{
    Debug.Log($"Raycast 충돌 @ {hit.collider.gameObject.name}!");
}

코드 분석:
1. TransformDirection 함수:

  • 로컬 좌표계의 Forward(0, 0, 1)를 월드 좌표계 기준으로 변환합니다.
  • 객체가 바라보는 방향에 따라 광선의 방향을 설정합니다.
  1. Physics.Raycast 인자:

    • 첫 번째 인자: 광선 시작점 (위 코드에서는 transform.position + Vector3.up).
      • Vector3.up을 더한 이유: 객체의 Pivot(기준점)이 발에 위치했기 때문에, 광선을 약간 위에서 발사하기 위해.
    • 두 번째 인자: 광선 방향 (위 코드에서는 look).
    • 세 번째 인자: 충돌한 객체의 정보를 저장할 RaycastHit 변수.
    • 네 번째 인자: 광선의 최대 길이 (위 코드에서는 10).
  2. RaycastHit 구조체:

    • 충돌한 객체의 Collider, Transform, Point, Normal 등을 포함합니다.
  3. Debug.Log:

    • 충돌한 객체의 이름을 출력합니다.

2. 여러 객체와 충돌 확인 (RaycastAll)

Vector3 look = transform.TransformDirection(Vector3.forward);
RaycastHit[] hits = Physics.RaycastAll(transform.position + Vector3.up, look, 10);

foreach (RaycastHit hit in hits)
{
    Debug.Log($"Raycast 충돌 @ {hit.collider.gameObject.name}!");
}

코드 분석:
1. Physics.RaycastAll 함수:

  • 하나의 광선으로 여러 객체와의 충돌을 확인합니다.
  • 반환값은 RaycastHit 배열입니다.
  1. foreach 루프:

    • 광선이 충돌한 모든 객체의 정보를 순회하며 출력합니다.
  2. 적용 사례:

    • 광선이 관통하면서 충돌한 모든 객체를 확인해야 할 때 사용합니다.

3. 화면에서 클릭한 위치를 기준으로 Raycast

if (Input.GetMouseButtonDown(0)) // 마우스 좌클릭
{
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); // 클릭한 위치를 기준으로 Ray 생성
    Debug.DrawRay(Camera.main.transform.position, ray.direction * 100.0f, Color.red, 1.0f); // Ray 시각화
    
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit, 100.0f))
    {
        Debug.Log($"Raycast Camera 충돌 @ {hit.collider.gameObject.name}!");
    }
}

코드 분석:
1. Input.GetMouseButtonDown(0):

  • 마우스 왼쪽 버튼 클릭 시 실행.
  1. ScreenPointToRay:

    • 카메라의 Screen 좌표계에서 클릭한 마우스 위치를 월드 좌표계로 변환하여 Ray를 생성합니다.
  2. Debug.DrawRay:

    • 생성된 Ray의 경로를 시각화하여 확인합니다.
  3. Physics.Raycast:

    • 생성된 Ray를 발사하고 충돌한 객체 정보를 확인합니다.

4. 특정 레이어만 Raycast 처리

int mask = (1 << 8) | (1 << 9); // 8번, 9번 레이어만 선택
if (Physics.Raycast(ray, out hit, 100.0f, mask))
{
    Debug.Log($"Raycast Camera 충돌 @ {hit.collider.gameObject.name}!");
}

코드 분석:
1. (1 << 8):

  • 8번 레이어를 선택하기 위해 비트를 왼쪽으로 8번 이동.
  • 예: 0000000100010000.
  1. | (OR) 연산:

    • 여러 레이어를 선택하기 위해 사용. 예: 8번과 9번 레이어 선택.
  2. maskPhysics.Raycast에 전달:

    • 특정 레이어의 객체와만 Raycast 충돌 검사를 수행합니다.

Raycasting 최적화

  1. 레이어 마스크 사용:

    • LayerMask를 활용하여 불필요한 객체를 Raycast 연산에서 제외.
  2. Raycast 길이 제한:

    • 광선의 길이를 필요 최소한으로 설정하여 성능을 개선.
  3. 충돌 조건 최소화:

    • 필요 없는 정보는 계산하지 않도록 코드 최적화.

투영(Screen, Viewport, World) 개념

  1. Screen 좌표계:

    • 화면상의 픽셀 단위로 좌표를 나타냅니다.
    • 왼쪽 아래가 (0, 0), 오른쪽 위가 (Screen.width, Screen.height).
  2. Viewport 좌표계:

    • 화면 좌표를 비율(0~1)로 변환하여 나타냅니다.
    • 왼쪽 아래가 (0, 0), 오른쪽 위가 (1, 1).
  3. World 좌표계:

    • 게임 월드에서의 실제 3D 공간 좌표를 나타냅니다.

화면 좌표를 월드 좌표로 변환하기

Vector3 mousePos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane));

분석:
1. Input.mousePosition:

  • 현재 마우스 위치를 Screen 좌표계로 가져옵니다.
  1. ScreenToWorldPoint:
    • Screen 좌표계를 World 좌표계로 변환합니다.
    • Z 값은 카메라와의 거리(nearClipPlane)로 설정.

Raycasting과 투영의 활용 사례

  1. 캐릭터와 장애물 감지:

    • Raycast를 활용해 캐릭터와 카메라 사이 장애물을 감지하고, 카메라 위치를 이동.
  2. 클릭 이벤트 처리:

    • 클릭한 위치로 Ray를 쏘아 해당 객체를 활성화하거나 이벤트 처리.
  3. 투사체 경로 확인:

    • Raycast로 투사체의 충돌 여부와 충돌 위치를 계산.

profile
李家네_공부방

0개의 댓글