Closest point for point towards a specific collider?

Hello,

I have a point and a PhysicsCollider. I want the closest point on the collider towards the point.
I only found solutions for specific checking all colliders with a specific filter.
But I already know the concrete PhysicsCollider.
Furthermore how to get the related normal of the vector from point towards closest point?
Is there some unity function for generic physicscollider or do I need to manually access the collidertype and calculate it on my own?

Here you should find what you are looking for, specifically in the Distance Query section.

I suppose the PointDistanceInput queries in the Collider would fit your needs.
Ex: Collider.CalculateDistance(PointDistanceInput, out DistanceHit)

1 Like

Thank you for the answer.

For some reason CalculateDistance() returns false. I am sure a collision is happening.

[BurstCompile(OptimizeFor = OptimizeFor.Performance)]
partial struct GetBoidObstacleCollisionDataJob : IJobParallelFor
{
    [ReadOnly] public int cellCountX;
    [ReadOnly] public int cellCountXY;
    [ReadOnly] public int areaCellCountX;
    [ReadOnly] public int areaCellCountXY;
    [ReadOnly] public int3 areaStartCell;
    [ReadOnly] public int3 areaCellOffset;

    [ReadOnly] public float boidObstacleInteractionRadius;

    [ReadOnly] public NativeArray<int3> hashPivots;
    [ReadOnly] public NativeArray<int> hashTable;
    [ReadOnly] public NativeArray<BoidData> boidDataArr;

    [ReadOnly] public PhysicsCollider collider;

    public NativeArray<ObstacleData> obstacleData;


    [BurstCompile(OptimizeFor = OptimizeFor.Performance)]
    public void Execute(int areaCellIndex)
    {
        int x = areaCellIndex % areaCellCountX;
        int z = /*(int)*/areaCellIndex / areaCellCountXY;
        int y = ((areaCellIndex % areaCellCountXY) - x) / areaCellCountX;
        int3 areaCell = new int3(x,y,z);

        int3 cell = areaStartCell + areaCell;
        int cellIndex = cell.x + cell.y * cellCountX + cell.z * cellCountXY;

        int3 pivot = hashPivots[cellIndex];
        for (int i = pivot.y; i < pivot.z; i++)
        {
            int boidIndex = hashTable[i];

            BoidData boidData = boidDataArr[boidIndex];
            float3 boidPosition = boidData.position;
            PointDistanceInput input = new PointDistanceInput();
            input.Position = boidPosition;
            input.MaxDistance = boidObstacleInteractionRadius;
            DistanceHit hit = new DistanceHit();

            if (collider.Value.Value.CalculateDistance(input, out hit))
            {
                if (hit.Distance < obstacleData[boidIndex].distance || obstacleData[boidIndex].distance == -1)
                {
                    float3 boidDirection = math.mul(boidData.rotation, new float3(0, 0, 1));
                    float3 rotationAxis = math.normalizesafe(math.cross(boidDirection, hit.SurfaceNormal));
                    float3 avoidanceDirection = math.mul(quaternion.AxisAngle(rotationAxis, 0.5f * math.PI), hit.SurfaceNormal);
                    obstacleData[boidIndex] = new ObstacleData
                    {
                        avoidanceDirection = avoidanceDirection,
                        distance = hit.Distance
                    };
                }
            }
        }
    }
}

Is it possible that a changed scale on the obstacle game objects is not accounted for?

Note that the PhysicsCollider alone, which is part of the rigid body, does not know where it is located in world space.
You need to bring the input into local space of the rigid body, as is done in this ApplyExplosionForce function:

As you can see, the scale of the rigid body entity is also taken into account.
To get the rigid body entity’s transformation, simply use the data from its LocalTransform component, which holds position, rotation and uniform scale.

1 Like