- Home /
Unity navmesh, navigate to closest point of clicked object
See the image to understand what I am trying to explain. I want to click on this tree and for the agent to find the closest point between it and the tree and navigate there, however it seems to just pick random points around each object and walks there. The best thing I could find which could possibly help is NavMesh.FindClosestEdge however I can't seem to get it to work with what I want to do with it. I tried on the Unity navigation forum and had no response in 48 hours.
if(Input.GetMouseButtonDown(0))
{
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
RaycastHit rayHit;
NavMeshHit navHit;
if(Physics.Raycast(ray, out rayHit))
{
float dist = Vector3.Distance(rayHit.point,transform.position);
//For general ground navigation
if(dist > .5f && rayHit.transform.gameObject.layer == LayerMask.NameToLayer("Ground"))
{
agent.SetDestination(rayHit.point);
}
//If click tree!
if(dist > .5f && rayHit.transform.gameObject.layer == LayerMask.NameToLayer("Tree"))
{
if (NavMesh.FindClosestEdge(rayHit.transform.position, out navHit, NavMesh.AllAreas))
{
DrawCircle(navHit.position, navHit.distance, Color.red);
Debug.DrawRay(navHit.position, Vector3.up, Color.red);
agent.SetDestination(rayHit.transform.position);
}
}
}
}
What i currently have above does not work, because i can only assume it's looking for an actual navmesh hit rather than a gameobject hit. Any help would be so greatly appreciated, i really can't understand how this isn't a common issue with Navmesh games.
Answer by unity_ek98vnTRplGj8Q · Feb 13, 2020 at 04:55 AM
First of all, this line agent.SetDestination(rayHit.transform.position);
sets the destination to the position of the gameobject that you clicked. This is why your agent is going to a random side, because your requested destination is right in the middle of the gap in the navmesh. Putting in navHit.position
or even rayHit.point
will likely yield more consistent results. If you want your player to go to the closest point to him, then an easy way could be to just nudge your destination towards your player, maybe something like
Vector3 playerDirection = transform.position - rayhit.transform.position;
agent.SetDestination(rayHit.transform.position + playerDirection.normalized);
Also as a note, I'm pretty sure (although I haven't used Unity's navmesh in a while), requesting a destination that is off the navmesh will automatically path you towards the closest location that is on the navmesh, so you don't have to go through the trouble of calculating it yourself
I'll try the "nudge" method later, but I have tried the regular rayHit.point and navhit.transform.position and both are exactly the same.
For now i have done a dirty hack by adding an empty gameobject around the tree which rotates towards the player with an offset to the tree, and clicking the tree will navigate to that invisible object.
I'll mark this answer as correct, because rayHit.point for even clicking on a gameobject does infact "almost" work the way i want it too. I think i spent so much time trying rayHit.transform.position assu$$anonymous$$g that I need to treat the hit as a gameobject rather than a regular hit that i never really tried just using the standard rayHit.point. Some more tweaking is needed to get it working perfectly but it's good enough for now thanks.