0
\$\begingroup\$

How can I check if one 2d collider (circle, capsule, polygon etc.) is completely inside / outside of a polygon collider?

\$\endgroup\$
  • \$\begingroup\$ Completely outside is easy: Physics2D.IsTouching(a, b) == false. Completely inside is more challenging, as it's not usually used in games for general shapes. We might special-case some math to check if something's fully inside a circular or rectangular trigger zone, though usually it's easier to make the zone smaller and ask about contact instead. What gameplay feature do you need your "completely inside" check to build? There might be easier ways of accomplishing that feature. \$\endgroup\$ – DMGregory Jul 6 at 11:37
  • \$\begingroup\$ I need to find out wether objects (placed by a level designer) of very different shapes and sizes reside on the polygon-shaped platform (that can be in different places). I need them to be completely inside the platform or else they will bump into walls of the platform. \$\endgroup\$ – Petro Koval Jul 6 at 11:56
  • \$\begingroup\$ So you need to verify that colliders of various types fit fully within a polygon (not inside a circle/capsule as described in your question) as an edit-time validation step, not something you want to do frequently at runtime? That makes the problem significantly easier. Can we make any guarantees about the containing polygon - eg. is it convex, can it contain holes? \$\endgroup\$ – DMGregory Jul 6 at 11:59
  • \$\begingroup\$ There will be no holes, but it is not always convex. It is in runtime, but only once per 15-20 seconds. \$\endgroup\$ – Petro Koval Jul 6 at 12:27
1
\$\begingroup\$

As noted in the comments, you can check whether two colliders do not intersect at all with:

Physics2D.IsTouching(colliderToCheck, polygonRegion) == false;

If the two colliders are touching, then you have two possibilities:

  1. the colliderToCheck is contained entirely inside the polygonRegion

  2. the colliderToCheck crosses the perimeter of the polygonRegion

So, if we want to eliminate case 2, then we just need to check each edge along the perimeter of the polygon.

For 3D colliders we could use Collider.Raycastto check just the one collider against a sequence of lines, but for some reason Collider2D.Raycast does the exact opposite thing, checking every other collider instead.

But, we can use the same IsTouching trick as before, just using a different collider. Add an EdgeCollider2D to the mix, setting edges.points = polygonRegion.points. Then you can check whether colliderToCheck is touching/crossing any edge of the polygon's perimeter, with a tolerance you can control via the edgeRadius parameter.

Note that IsTouching just queries the contact state as of the last physics step. If you've moved your colliders around, you'll need to SyncTransforms() to update the contact information. It also only works if the physics engine is checking for collisions/overlaps between the colliders in the first place, so they can't be both static or both kinematic (cases the physics engine ignores, since by marking them that way you've told it you don't want it to process those collisions).

\$\endgroup\$
  • \$\begingroup\$ Thanks a lot! That is exactly what I needed! \$\endgroup\$ – Petro Koval Jul 6 at 16:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.