AABB,OBB 와 Unity Collider

JJW·2025년 2월 12일
0

Unity

목록 보기
21/34

오늘은 충돌 감지에 사용되는 AABB와 OBB에 대해서 알아보고 Unit Collider에 어떻게 적용되는지에 대해 알아보겠습니다.


AABB

정의

➡️ AABB (Axis - Aligned Bounding Box)는 이름에서 알 수 있듯이 상자의 모든 면이 전역 좌표계의 x,y,z 축과 평행하도록 정의됩니다.

장단점

  • 장점

    • 두 AABB 간의 충돌 여부는 각 축에 대해 최소/최대 값의 범위가 겹치는지만 확인하므로 계산이 굉장히 빠릅니다.
    • 많은 객체들이 있을 때 빠르게 후보 충돌 쌍을 거르기 위해 널리 사용됩니다.
  • 단점

    • 객체가 회전하거나 비정형인 경우 AABB는 실제 객체보다 훨씬 큰 영역을 감싸게 되어 불필요한 충돌 검사가 발생할 수 있습니다.
    • 객체의 로컬 형태와 실제 월드 공간에서의 모양이 달라질 수 있습니다.

코드

        if (col != null)
        {
            Gizmos.color = Color.blue;
            Bounds aabb = col.bounds;
            Gizmos.DrawWireCube(aabb.center, aabb.size);
        }
  • Unity의 Collider.bouns는 월드 좌표계에서 축에 정렬된 경계 상자를 반환합니다.

OBB

정의

➡️ OBB (Oriented Bounding Box)는 객체의 회전 상태나 기하학적 형태를 반영하여 상자가 객체에 맞게 회전된 형태로 정의됩니다.

장단점

  • 장점

    • 회전하는 객체에 대해 실제 모양에 근접하는 경계체를 제공하여 불필요한 충돌 검사를 줄입니다.
  • 단점

    • 두 OBB 사이의 충돌 검사는 복잡한 알고리즘을 사용해야 하므로 연산 비용이 높습니다.
    • 객체의 변환이 있을 때마다 경곛체를 갱신해야 하므로 관리가 복잡할 수 있습니다.

코드

        if (box != null)
        {
            Gizmos.color = Color.red;
            Vector3[] corners = GetBoxColliderCorners(box);

            // 12개의 엣지를 그려서 OBB를 시각화

            // 바닥 면 (0, 1, 2, 3)
            DrawLine(corners[0], corners[1]);
            DrawLine(corners[1], corners[2]);
            DrawLine(corners[2], corners[3]);
            DrawLine(corners[3], corners[0]);

            // 윗면 (4, 5, 6, 7)
            DrawLine(corners[4], corners[5]);
            DrawLine(corners[5], corners[6]);
            DrawLine(corners[6], corners[7]);
            DrawLine(corners[7], corners[4]);

            // 수직 엣지
            DrawLine(corners[0], corners[4]);
            DrawLine(corners[1], corners[5]);
            DrawLine(corners[2], corners[6]);
            DrawLine(corners[3], corners[7]);
        }
        
     // BoxCollider의 로컬 코너를 월드 공간으로 변환하여 OBB의 8개 코너를 반환합니다.
    Vector3[] GetBoxColliderCorners(BoxCollider boxCollider)
    {
        Vector3[] corners = new Vector3[8];

        // BoxCollider의 로컬 중심과 크기를 가져옴
        Vector3 center = boxCollider.center;
        Vector3 size = boxCollider.size;
        Vector3 half = size * 0.5f;

        // 로컬 공간에서 8개의 코너 계산
        corners[0] = center + new Vector3(-half.x, -half.y, -half.z);
        corners[1] = center + new Vector3(half.x, -half.y, -half.z);
        corners[2] = center + new Vector3(half.x, -half.y, half.z);
        corners[3] = center + new Vector3(-half.x, -half.y, half.z);
        corners[4] = center + new Vector3(-half.x, half.y, -half.z);
        corners[5] = center + new Vector3(half.x, half.y, -half.z);
        corners[6] = center + new Vector3(half.x, half.y, half.z);
        corners[7] = center + new Vector3(-half.x, half.y, half.z);

        // 각 코너를 GameObject의 월드 좌표로 변환
        for (int i = 0; i < corners.Length; i++)
        {
            corners[i] = boxCollider.transform.TransformPoint(corners[i]);
        }
        return corners;
    }
  • BoxCollider는 로컬 공간에서 center와 size로 정의됩니다.
  • GetBoxColliderCorners() 함수를 통해 로컬 공간에서의 8개의 코너를 계산한 후 TransformPoint를 통해 월드 공간의 좌표로 반환합니다.

테스트

➡️ 파란색 : AABB
➡️ 빨간색 : OBB

  • 회전을 할 때 AABB의 경우 단점에서 언급한 것 처럼 실제보다 큰 영역을 감싸는 모습을 확인할 수 있습니다.
  • 회전을 할 때 OBB의 경우 실제 오브젝트의 영역의 모습을 유지하는 것을 확인할 수 있습니다.

Unity Collider와의 관계

  • Unity의 Collider는 내부적으로 AABB와 OBB의 개념을 모두 활용한다고 합니다.
  • 콜라이더의 크기와 중심을 지정할 때 별도의 회전 정보 없이 단순한 AABB 형태로 설정되고 회전이 적용되면 로컬 AABB가 월드 공간으로 변화되며 사실상 OBB처럼 작동한다고 합니다.

결론

  • Collider 사용이 많은 편리함을 가져다 주었다..
profile
Unity 게임 개발자를 준비하는 취업준비생입니다..

0개의 댓글