- Home /
Shortest distance between two meshes/colliders
I have two objects with a significant size difference. I want to find the shortest possible distance between those objects. For example, if I have a small chair in front of a wall. I want the distance between the chair and the wall. I tried using Vector3.distance
, but it calculates using world coordinates. I tried using colliders to achieve this as I had read somewhere that it was the solution but was unclear on how to go about it. Can someone please help?
I have added an image to illustrate what I want. the drawing on the left is of the camera view and the right is a side view. The red line is the distance I get when I use Vector3.Distance
, however the distance I want is the green line. If there are many objects in the game, how can I get the shortest distance between the two objects I have selected. I have seen a few solutions but none of them seem to work for me.
Answer by andrew-lukasik · Jul 28, 2021 at 10:54 AM
This is one of those simple questions that can easily require horrendously complicated answer to cover this subject.
I for one came up with a solution using SDF
equations working with Bounds
. It's not ideal, but it's fast, simple, allocates no memory - good enough for many use cases.
pros: it works
cons: approximates colliders/meshes to their
AABB
// src* = https://gist.github.com/andrew-raphael-lukasik/658184336c9799ed66f3a5acfa3e7f9c
using UnityEngine;
public class CalculateDistanceBetweenColliderBounds : MonoBehaviour
{
[SerializeField] Collider collider0;
[SerializeField] Collider collider1;
void OnDrawGizmos ()
{
if( collider0==null || collider1==null ) return;
Bounds bounds0 = collider0.bounds;
Bounds bounds1 = collider1.bounds;
float sd0 = sdBounds( bounds0.center , bounds1 , out Vector3 conjecture0 );
float sd1 = sdBounds( bounds1.center , bounds0 , out Vector3 conjecture1 );
float dist = Vector3.Distance( conjecture0 , conjecture1 );
Gizmos.color = new Color(0,1,1,0.2f);
Gizmos.DrawCube( bounds0.center , bounds0.size ); Gizmos.DrawCube( bounds1.center , bounds1.size );
Gizmos.DrawWireCube( bounds0.center , bounds0.size ); Gizmos.DrawWireCube( bounds1.center , bounds1.size );
UnityEditor.Handles.Label( transform.position , $"approx distance: {dist}" );
}
static float sdBounds ( Vector3 point , Bounds bounds , out Vector3 contact )
{
Vector3 dir = point - bounds.center;
float sd = sdBox( dir , bounds.extents );
contact = point - dir.normalized*sd;
// note: we dont need to know the real contact point in this case, this is pure conjecture
return sd;
}
// src: https://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
static float sdBox ( Vector3 p , Vector3 b )
{
Vector3 q = new Vector3( Mathf.Abs(p.x) , Mathf.Abs(p.y) , Mathf.Abs(p.z) ) - b;
return Vector3.Magnitude(Vector3.Max(q,Vector3.zero)) + Mathf.Min(Mathf.Max(q.x,Mathf.Max(q.y,q.z)),0f);
}
}
Answer by SoulBlaze06 · Jul 28, 2021 at 09:21 AM
I didn't understand properly. Is your wall curved and not straight and you want the distance from the curved point instead from the centre of wall. If so, then you can simply parent another object to your wall , position it to your desire and then instead of checking the distance between chair and wall, you can check the distance between player and the parented object of wall. You can use Vector3.Distance() for this.
It's straight. i just drew it at an angle to show it's orientation with respect to the main camera. I have a lot of objects in the scene, so parenting might not be an option.
Answer by Saiguru · Jul 28, 2021 at 10:32 AM
You can try with the 3 rays from the objects from the same origin but of different angles and with RaycastHit distance whichever is the shortest you can identify using conditions.
Seems like an interesting solution. I'll check it out. Thank you
Your answer
Follow this Question
Related Questions
Get x and y Distance between two Vectors 1 Answer
GameObject's transform in Vector3 1 Answer