I am using the navmesh/agent on the player as an assistance autopathing function where the agent is disabled at all times unless the user clicks a point on the floor to walk towards. Then the agent will be disabled again once the destination is reached.
I need a way to check if the player is currently on the navmesh, within a tolerable threshold without the navmeshagent being enabled. Or, if there is a way to remove the player-binding 'effect' of the navmeshagent without disabling it, as I could use that to solve my problem too.
I guess in pseudocode, this is what i'm trying to accomplish with navmeshagent disabled:
if (!agent.isOnNavMesh){ DisableClickSelection();}
I was thinking of the possibility of comparing the Y transform of the player and the navmesh to get a height difference and using that to determine if the player is on the navmesh but i don't know how to go about getting the Y transform of the navmesh at a specific X and Z point. Maybe i can use a raycast? I'm not sure the best way. Like i said, if there is a way to remove the player-binding 'effect' of the agent on the player but keep the agent enabled I would be able to work with that too.
You should be able to do this through use of NavMesh.SamplePosition()
. This method basically searches in a spherical radius around a given position for the nearest point on the navmesh. All you need to do is verify that the returned position is vertically in line with the player position, and is on/above it.
Here's an idea on how you might apply this in code:
// Don't set this too high, or NavMesh.SamplePosition() may slow down
float onMeshThreshold = 3;
public bool IsAgentOnNavMesh(GameObject agentObject)
{
Vector3 agentPosition = agentObject.transform.position;
NavMeshHit hit;
// Check for nearest point on navmesh to agent, within onMeshThreshold
if (NavMesh.SamplePosition(agentPosition, out hit, onMeshThreshold, NavMesh.AllAreas))
{
// Check if the positions are vertically aligned
if (Mathf.Approximately(agentPosition.x, hit.position.x)
&& Mathf.Approximately(agentPosition.z, hit.position.z))
{
// Lastly, check if object is below navmesh
return agentPosition.y >= hit.position.y;
}
}
return false;
}
So for using it with your example, you'd write:
if (!IsAgentOnNavMesh(agent.gameObject))
{
DisableClickSelection();
}
Hope this helps! Let me know if you have any questions.