Well your issue is pretty simple:
You are checking the distance between the player position and the ray direction!
Of course this makes absolutely no sense since it basically equals the Camera.main.transform.forward
. If you use a normalized direction like a position it will basically be something around the Unity origin at a distance of 1. While your player could be positioned just anywhere. You want to check the distance between player and hitInfo.point
!
// If possible already reference this in the Inspector
[SerializeField] private Camera _camera;
private void Awake ()
{
// As fallback get the camera ONCE on runtime, "Camera.main" is expensive!
//see https://docs.unity3d.com/ScriptReference/Camera-main.html
if(!_camera) _camera = Camera.main;
}
private void Update()
{
var ray = _camera.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray, out hitInfo)
{
// Get the position where exactly you hit something
var hitPoint = hitInfo.point;
// Regardless of what we hit eliminate any difference in the Y axis
hitPoint.y = 0;
// also map the player position on the XZ plane (erase any Y axis height)
var playerPosition = transform.position;
playerPosition.y = 0;
// Now you get the correct distance between both points in the XZ plane
var distance = Vector3.Distance(hitPoint, playerPosition);
Debug.Log($"Distance: {distance}", this);
}
}
What I would use in your case is the intersection point of the ray and the Playboard - assuming the Unity XZ Plane
.
And then get the distance between your player position mapped onto that XZ plane and the ray hit point in the XZ plane.
The advantage of this is that this is pure mathematical and doesn require any colliders and can not break if a different collider is in the way.
Something like
// If possible already reference this in the Inspector
[SerializeField] private Camera _camera;
// First parameter is the global UP axis -> we get the flat floor in XZ axis
// For the second parameter you could e.g. change the Y component if there needs
// to be a ground height different to 0
// see https://docs.unity3d.com/ScriptReference/Plane-ctor.html
private Plane _xzPlane = new Plane(Vector3.up, Vector3.zero);
private void Awake ()
{
// As fallback get the camera ONCE on runtime, "Camera.main" is expensive!
//see https://docs.unity3d.com/ScriptReference/Camera-main.html
if(!_camera) _camera = Camera.main;
}
private void Update()
{
var ray = _camera.ScreenPointToRay(Input.mousePosition);
// Directly use a raycasts on the XZ plane -> pure mathematical doesn't need any collider/physics
// see https://docs.unity3d.com/ScriptReference/Plane.Raycast.html
if(plane.Raycast(ray, out hitDistance)
{
// get the position where we hit the XZ plane
// see https://docs.unity3d.com/ScriptReference/Ray.GetPoint.html
var xzHitPoint = ray.GetPoint(hitDistance);
// map the player position on the XZ plane (erase any Y axis height)
// see https://docs.unity3d.com/ScriptReference/Plane.ClosestPointOnPlane.html
var xzPlayerPosition = plane.ClosestPointOnPlane(transform.position);
// Now you get the correct distance between both points in the XZ plane
var distance = Vector3.Distance(xzHitPoint, xzPlayerPosition);
Debug.Log($"Distance: {distance}", this);
}
}
API links are in the code comments.