- Home /
pick random point on navmesh
hi ive looked at the other questions regarding this but havent found what i want i wish to pick a random point on the navmesh set that as my ai's destination and when he reaches it pick another random point has anyone found a way to do this? even if you only know how to check when ai has stoped or reached its destination id also like to know this
Both of your questions are already answered on here:
http://answers.unity3d.com/questions/324589/how-can-i-tell-when-a-navmesh-has-reached-its-dest.html
http://answers.unity3d.com/questions/475066/how-to-get-a-random-point-on-navmesh.html
Edit: corrected second link to another question ins$$anonymous$$d of this one!
first one i knew about but dosent explain how to use it second one is my question :P
I would use this for random point : http://docs.unity3d.com/ScriptReference/Random-insideUnitCircle.html and this to check if that random point is on the nav mesh : http://docs.unity3d.com/ScriptReference/Nav$$anonymous$$esh.SamplePosition.html
Whoops! Thanks Xtro, had this question and the one with the answer open in two tabs and grabbed the wrong URL to post haha.
Answer by PvTGreg · Dec 20, 2014 at 09:16 PM
if (DoWaypoints == true)
{
float dist = GetComponent<NavMeshAgent>().remainingDistance;
if (dist!=Mathf.Infinity && GetComponent<NavMeshAgent>().pathStatus== NavMeshPathStatus.PathComplete && GetComponent<NavMeshAgent>().remainingDistance==0)//Arrived.
{
Wonder();
}
}
void Wonder()
{
Vector3 randomDirection = Random.insideUnitSphere * walkRadius;
randomDirection += transform.position;
NavMeshHit hit;
NavMesh.SamplePosition(randomDirection, out hit, walkRadius, 1);
Vector3 finalPosition = hit.position;
GetComponent<NavMeshAgent>().destination = finalPosition;
}
Answer by Puck · Feb 19, 2017 at 10:56 PM
For anyone coming here from Google, I encountered this same issue where I wanted to place my agents randomly on pathable terrain and I came up with the following solution for Unity 5.5.
Vector3 GetRandomLocation()
{
NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation();
// Pick the first indice of a random triangle in the nav mesh
int t = Random.Range(0, navMeshData.indices.Length-3);
// Select a random point on it
Vector3 point = Vector3.Lerp(navMeshData.vertices[navMeshData.indices[t]], navMeshData.vertices[navMeshData.indices[t+1]], Random.value);
Vector3.Lerp(point, navMeshData.vertices[navMeshData.indices[t+2]], Random.value);
return point;
}
The distribution isn't uniform, but it works well enough for my purpose.
Answer by batteryyrettab · Jun 08, 2018 at 01:04 AM
A modification to Puck's answer to make it a little more uniform is
Vector3 GetRandomLocation()
{
NavMeshTriangulation navMeshData = NavMesh.CalculateTriangulation();
int maxIndices = navMeshData.indices.Length - 3;
// Pick the first indice of a random triangle in the nav mesh
int firstVertexSelected = Random.Range(0, maxIndices);
int secondVertexSelected = Random.Range(0, maxIndices);
//Spawn on Verticies
Vector3 point = navMeshData.vertices[navMeshData.indices[firstVertexSelected]];
Vector3 firstVertexPosition = navMeshData.vertices[navMeshData.indices[firstVertexSelected]];
Vector3 secondVertexPosition = navMeshData.vertices[navMeshData.indices[secondVertexSelected]];
//Eliminate points that share a similar X or Z position to stop spawining in square grid line formations
if ((int)firstVertexPosition.x == (int)secondVertexPosition.x ||
(int)firstVertexPosition.z == (int)secondVertexPosition.z
)
{
point = GetRandomLocation(); //Re-Roll a position - I'm not happy with this recursion it could be better
}
else
{
// Select a random point on it
point = Vector3.Lerp(
firstVertexPosition,
secondVertexPosition, //[t + 1]],
Random.Range(0.05f, 0.95f) // Not using Random.value as clumps form around Verticies
);
}
//Vector3.Lerp(point, navMeshData.vertices[navMeshData.indices[t + 2]], Random.value); //Made Obsolete
return point;
}
Example usage might look like this: (including a variant to only spawn on certain areas of the Nav$$anonymous$$esh. Use 8, 16, 32, etc. for each layer)
//Declare these:
private Nav$$anonymous$$eshHit navmeshHit;
public bool spawnOnArea = false;
//Usage:
for (int i = 0; i < 50; i++)
{
if (!spawnOnArea)
{ GameObject.CreatePrimitive(PrimitiveType.Sphere).transform.position = GetRandomLocation();
}
else
{
Vector3 spotToSpawn = GetRandomLocation();
if (Nav$$anonymous$$esh.SamplePosition(spotToSpawn, out navmeshHit, 1, Nav$$anonymous$$esh.AllAreas))
{
if (navmeshHit.mask == 8)
{ GameObject.CreatePrimitive(PrimitiveType.Sphere).transform.position = spotToSpawn;
}
}
}
}
Answer by Mmmpies · Dec 19, 2014 at 02:32 PM
That second one searches for the closest point on a navmesh to the given location but it takes a float to say how far away from the random location to check so just set that high enough and it'll find a valid location on the navmesh nearest to your random location.
Not sure how much performance hit it is though.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
I'm trying to make AI that walks (and faces) towards a waypoint 1 Answer
AI in unity, need help 1 Answer
Navmesh Trouble 1 Answer
NavMesh flee. Ai flee from player. 4 Answers