[유니티] Physics.OverlapCapsule 사용법

7773 단어 unitycsharp
2021-09-06 업데이트: 이 글은 부착된 게임 오브젝트의 회전과 CapsuleCollider의 방향을 고려하여 크게 수정되었습니다.


Physics.OverlapCapsule를 사용하여 위와 같이 CapsulCollider와 겹치는 두 개의 Collider를 얻을 수 있습니다. 이 메서드는 캡슐의 위치와 크기를 가져오고 캡슐과 겹치는 모든 Collider를 반환합니다.

Kinematic Rigidbody Trigger Collier를 구성하고 OnTriggerEnter 메시지를 처리하여 충돌체를 가져올 수도 있지만 이 방법은 편리하고 유용한 응용 프로그램이 있습니다.

다음은 Physics.OverlapCapsule 의 선택적 인수가 없는 서명을 보여줍니다.

Collider[] OverlapCapsule(Vector3 point0, Vector3 point1, float radius);


다음 그림의 왼쪽은 이러한 인수를 보여줍니다. point0point1 각각은 반구 중 하나의 중심을 갖습니다. radius에는 반지름이 있습니다. 오른쪽에 있는 CapsuleCollider의 사양에는 중심, 높이 및 반경이 있습니다. 그것들은 상당히 다르므로 변환해야 합니다.



다음은 CapsuleCollider의 point0point1를 계산하는 방법을 보여줍니다. 계산 시 CapsuleCollder의 방향 속성을 고려해야 합니다. 이 속성은 각각 X, Y 또는 Z축에 해당하는 0, 1 또는 2일 수 있습니다.

var col = GetComponent<CapsuleCollider>();
var direction = new Vector3 {[col.direction] = 1};
var offset = col.height / 2 - col.radius;
var localPoint0 = col.center - direction * offset;
var localPoint1 = col.center + direction * offset;


월드 공간에서 point0point1를 지정해야 합니다.

var point0 = transform.TransformPoint(localPoint0);
var point1 = transform.TransformPoint(localPoint1);


Physics.OverapCapsule의 radius에 대해 CapsuleCollider의 반지름을 월드 공간으로 변환해야 합니다. 그러나 간단하지 않습니다. 부착된 게임 오브젝트가 방향과 수직인 면에서 타원형이면 CapsuleCollider의 반지름을 긴 지름 쪽으로 확장해야 합니다.

다음은 이 변환의 구현을 보여줍니다. TransformVector에서 반환된 벡터의 일부 구성 요소는 마이너스일 수 있습니다.

var r = transform.TransformVector(col.radius, col.radius, col.radius);
var radius = Enumerable.Range(0, 3).Select(xyz => xyz == col.direction ? 0 : r[xyz])
    .Select(Mathf.Abs).Max();


마지막으로 지금까지 계산된 값으로 Physics.OverlapCapsule를 호출할 수 있습니다.

var cols = Physics.OverlapCapsule(point0, point1, radius);


반환된 Colliders에는 당연히 CapsuleCollider가 포함되어 있습니다. 제외하고 싶다면 미리 비활성화할 수 있습니다.
Physics.OverlapCapsule는 방금 터치한 충돌체를 결과에서 제외하기 위해 약간 더 작은 크기를 지정할 수 있어 매우 유용합니다. 거의 충돌하는 Colliders를 얻기 위해 더 큰 크기를 줄 수도 있습니다.

그런데 Physics.OverlapCapsule는 각 호출에서 결과를 저장하기 위해 배열을 할당하고 반환하므로 모든 프레임에서 호출할 때 많은 할당이 발생합니다.

이 경우 Physics.OverlapCapsuleNonAlloc 를 사용해야 합니다. 이 변형은 미리 할당된 배열에 결과를 저장합니다. 사용법은 아래와 같습니다.

class DetectOverlap
{
    readonly Collider[] _result = new Collider[5];

    void Update()
    {
        ...
        var num = Physics.OverlapCapsuleNonAlloc(point0, point1, radius, _result);
    }
}


이 사용법에서 Physics.OverlapCapsuleNonAlloc는 최대 5개의 중첩된 Collider를 감지할 수 있습니다. 이 메서드는 업데이트 외부에 할당된 5개의 충돌체 배열을 가져와 배열에 결과를 저장하고 숫자를 반환합니다.

좋은 웹페이지 즐겨찾기