[Unity] How to Use Physics.OverlapCapsule
Tags: unity3d, csharp
Published: 2020-09-25 13:03:03

Updated on 2021-09-06: This article was largely revised to take into account the rotation of the attached game object and the direction of the CapsuleCollider.

![A CapsuleCollider collides with two Colliders](https://dev-to-uploads.s3.amazonaws.com/i/o6897syzykdgpzhlwuvl.png)

You can use `Physics.OverlapCapsule` to get the two Colliders overlapped with the CapsulCollider as above. This method takes the position and size of a capsule and returns all Colliders overlapped by the capsule.

You can also get the Colliders by configuring a Kinematic  Rigidbody Trigger Collier and handling the `OnTriggerEnter`  message, but the method is handy and has useful applications.

The following shows the signature without optional arguments of `Physics.OverlapCapsule`.

```csharp
Collider[] OverlapCapsule(Vector3 point0, Vector3 point1, float radius);
```
The left side of the following figure illustrates these arguments. Each of `point0` and `point1` has the center of either of the hemispheres. The `radius` has the radius. The specs of a CapsuleCollider on the right side have its center, height, and radius. They are quite different, so you need to convert them. 

![Arguments of Physics.OverlapCupsule and specs of a CapsuleCollider](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xmxi0s26maz9gidljc5.png)

The following shows how to calculate the `point0` and `point1` for the CapsuleCollider.  The calculation must take into account the direction property of the CapsuleCollder, which can be 0, 1, or 2 correspondings to X, Y, or Z-axis, respectively.

```csharp
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;
```

We must specify the `point0` and `point1` in the world space.

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

We must translate the radius of the CapsuleCollider to the world space for the `radius` of Physics.OverapCapsule. But, it is not simple. If the attached game object is elliptic on the surface perpendicular to the direction, it is necessary to expand the radius of the CapsuleCollider to the long diameter side.

The following shows the implementation of this translation.  Please notice that some components of the vector returned by the `TransformVector` can be minuses.

```csharp
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();
```

Finally, we can invoke `Physics.OverlapCapsule` with the values calculated so far.

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

Notice that the returned Colliders naturally include the CapsuleCollider. You can disable it in advance if you want to exclude it.

`Physics.OverlapCapsule` is so useful that you can give it a slightly smaller size to exclude just touched Colliders from the result. You can also give it a larger size to get almost colliding Colliders.

By the way, `Physics.OverlapCapsule` allocates and returns an array to store the results in each invocation, so it causes a lot of allocation when you invoke it on every frame.

In this case, you should use `Physics.OverlapCapsuleNonAlloc`. This variant stores the results to an array allocated in advance. The usage is shown below.

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

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

In this usage, `Physics.OverlapCapsuleNonAlloc` can detect up to 5 overlapped Colliders. The method takes an array of 5 Colliders allocated outside Update, stores the results in the array, and returns the number.