Check if position is inside a collider

Hey all, This is for a teleport feature.

I am about to write a method that returns if a position is inside of a collider. That way I can negate the teleport, so the player doesn’t go inside of objects.

Does unity have some magic way of doing this?

I have an idea of how I can do it, but I wanted to ask here first in case there was an built in way / simple way one of you guys knew of.

Thanks

Guys I found a good simple way of doing this. Thanks for the responses.
Here is a hunk of code.

I used a SweepTest on my Rigidbody, I used distance and direction of my teleport location and used it as the ray to send out. I tested the what my RaycastHit got assigned to like this.

if( hitToTest.collider.bounds.Contains(telePosition) )
{
   print("point is inside collider");
}

Check out unity SweepTest() and Collider.bounds for specific syntax and what not.

Almost same: we used in the end:

public static bool IsInside ( Collider c , Vector3 point )
{
    Vector3 closest = c.ClosestPoint(point);
    // Because closest=point if point is inside - not clear from docs I feel
    return closest == point;
}

@s4vi0r has a good solution if you’re using Box Colliders, but a lot of us are asking about colliders in general, which would include spheres, capsules, and Mesh Colliders.

The solution bellow should account for these in a generic manner.


I should note that MeshColliders marked for triggers must also be marked convex, for similar reasons the MeshColliders you check with this code must also be convex or you may receive erroneous results.

However this code could be modified for an IsBelow() method for use with static MeshColliders you might have for terrain.

bool IsWithin(Collider c, Vector3 point, bool useRigidbody)
{
    Vector3 closest = c.ClosestPoint(point);
    Vector3 origin = c.transform.position + (c.transform.rotation * c.bounds.center);

    Vector3 originToContact = closest-origin;
    Vector3 pointToContact = closest-point;
  
    // If you're checking if a point is within a moving rigidbody and want to use it instead (ideally a single collider rigidbody; multiple could move the center of mass between the colliders, placing it "outside" and returning false positives). 
    Rigidbody r = c.attachedRigidbody;
    if (useRigidbody && (r != null))
    {
        // The benefit of this is the use of the center of mass for a more accurate physics origin; we multiply by rotation to convert it from it's local-space to a world offset.
        originToContact = closest - (r.position + (r.rotation * r.centerOfMass));
    }

    // Here we make the magic, originToContact points from the center to the closest point. So if the angle between it and the pointToContact is less than 90, pointToContact is also looking from the inside-out.
    // The angle will probably be 180 or 0, but it's bad to compare exact floats and the rigidbody centerOfMass calculation could add some potential wiggle to the angle, so we use "< 90" to account for any of that.
    return (Vector3.Angle(originToContact, pointToContact) < 90);
}

See this solution if you’re looking to do checks on concave MeshColliders, but it’s certainly overkill otherwise so pick the solution that works for you.

You can use triggers to check if objects are colliding. In the collider inspector of your object, turn on Is Trigger. Then you can create a script on your object that sends out values using the OnTriggerEnter(){}, OnTriggerStay(){} and OnTriggerExit(){} methods.

Edit:

You could make your teleport OnTriggerEnter(){} method modify the location of the character easily. You can access your players location from that method and change it.

Make sure one of the colliding objects is a Rigidbody, since it wont trigger with an other static collider. Check the Collision action matrix here for more information on triggers and what will trigger them.

Also, the 3d platform tutorial covers teleports IRC. Their solution might be more complete than mine, can’t remember how they did it though.

What you need is OverlapPoint():

Collider2D collider;
Vector2 point;
if( collider.OverlapPoint(point) )
{
    //do stuff
}

If this is a 2D game, I wrote this simple method that would check whether a given position is inside a collider:

public static bool IsPosInsideCollider(Vector3 _pos, LayerMask blockLayers, out Collider2D _hit)
{
    _hit = Physics2D.OverlapPoint(_pos, blockLayers); //note: OverlapPointAll gets all colliders at point 
    return _hit != null;
}

Use OverlapCircle if you are looking for colliders around a position (e.g. accounting for your character’s size), and not at an exact point.

If you are using a composite collider, go to the composite and set its “Geometry Type” to “polygons”, which have insides for the point to overlap. The default “Outlines” geometry are empty on the inside.

In 3D, just do OverlapSphere with a negligible radius instead. You can also do “nonalloc” versions of those casts to not allocate memory, if all you need to know if whether a collider is at a given point.