The Problem
My goal is to write a static method that gets an evenly distributed random point on a NavMesh.
I expect for everytime I call this method to get a random Vector3
that is a point on the mesh, which is currently working, however, the distribution leaves much to be desired.
Logistics
Unity 2022.3.19f1
.
Some information about the floor object
Here is the child, aka the actual mesh
To summarize textually when i get localScale
it's 1,1,1 and lossyScale
is 200,200,200
Code
using System;
using UnityEngine;
using UnityEngine.AI;
public static class SpawnUtils
{
//Offset to ensure GameObjects aren't spawned near edge
private const int NAV_MESH_OFFSET = 20;
private const int MAX_ATTEMPTS = 5;
private static GameObject floor;
public static Vector3 GetRandomSpawnPosition()
{
GameObject floor = GetFloor();
NavMeshHit hit = new();
int attempts = 0;
bool foundPoint = false;
float maxX = floor.transform.position.x + floor.transform.lossyScale.x / 2 - NAV_MESH_OFFSET;
float maxZ = floor.transform.position.z + floor.transform.lossyScale.z / 2 - NAV_MESH_OFFSET;
float minX = floor.transform.position.x - floor.transform.lossyScale.x / 2 + NAV_MESH_OFFSET;
float minZ = floor.transform.position.z - floor.transform.lossyScale.z / 2 + NAV_MESH_OFFSET;
// see my note on this variable
float maxDistance = 100;
while (!foundPoint && attempts < MAX_ATTEMPTS)
{
float x = UnityEngine.Random.Range(minX, maxX);
float z = UnityEngine.Random.Range(minZ, maxZ);
float y = floor.transform.position.y + floor.transform.lossyScale.y / 2;
Vector3 randomPoint = new(x, y, z);
foundPoint = NavMesh.SamplePosition(randomPoint, out hit, maxDistance, NavMesh.AllAreas);
attempts++;
}
if (!foundPoint)
{
Debug.LogError($"Failed to find a spawnable area within the maximum number, {MAX_ATTEMPTS} attempts.");
return floor.transform.position;
}
return hit.position;
}
public static GameObject Floor
{
...
}
public static GameObject GetFloor()
{
...
}
public static Vector3 GetSpawnableArea(Vector3 origin, float maxDistance)
{
...
}
}
Regarding float maxDistance
, this variable appears the be most influential and the cause of most of my misunderstanding, I imagined that it just tells the SamplePosition
method how far of a search range to go from randomPoint
and stop once the minimum distance required is found.
However, there seems to be a discrepancy here, adjusting the variable in increments of 50 leads to everything spawning either at the edge or in the dead center.
Examples
Now here it begins to get sensitive
Now once, I'm at this 100 mark, I encounter this strange distribution where objects are spawned at the center AND edges
I'll spare the last image since from 80 downwards, it's almost consistently at the origin Vector3(0,0,0)