I want to generate objects in a random position in a 2d plane and what I have so far gets the job done for the most part, however, I also want the objects to have a minimum distance from each other

public GameObject[] SpawnList = new GameObject[3];
public List<GameObject> objectsCreated = new List<GameObject>();
public int SpawnCount { get; set; }
// Update is called once per frame
private void Update()
{
if(SpawnCount <= 50)
{
var objectToSpawn = SpawnList[Random.Range(0, SpawnList.Length)];
var x = Random.Range(9,152);
var y = Random.Range(-1,3);
var pos = new Vector3(x, y, 0);
Instantiate(objectToSpawn, pos, Quaternion.identity);
objectsCreated.Add(objectToSpawn);
SpawnCount++;
}
}
}

mmm, tricky one. Youâ€™ll need to keep track of where everything is spawned (on the 1-unit grid thatâ€™s created with the int Random.Range), then check any new values against it, probably with Vector3.Distance.

What do you mean by â€ścertain distanceâ€ť, exactly? Some specific distance, or a minimum distance? This would make a difference in how you proceed. Both could use a while loop when choosing the new pos variable, so it will keep choosing until a valid one is selected. Note that as you fill up and less spaces are valid, you might get lags or freezes as it tries to find a spot.

Maybe thereâ€™s a simpler solution, but I donâ€™t have oneâ€¦curious to see what others come up with.

One method would be to check wether a new coordinate is close to an object already created and create a new coordinate if so as seejayjames suggested. But if you have lots of objects it gets more and more likely that you get â€ścollisionsâ€ť and if there are too much objects you can get an infinite loop. Another approach would be to generate a virtual grid of possible coordinates in your range and then â€śdrawâ€ť random positions from it (and delete them in the collection). This way you always have a valid one as long as there are coordinates remaining, If you need to break the grid pattern you could additionally shift the objects along a small random position vector within the grid cell.

This is NOT the minimum distance between the objects, but this is one technique I love to use for fairly-evenly covering a 2D area with N items, without too much clumping, and with almost zero extra processing / time:

iterate from 0 to N-1

derive one coordinate evenly from start to finish

derive one coordinate randomly

Thereâ€™s still open places but far less clumping.

int Count = 123;
int Width = 200;
int Depth = 400;
for (int i = 0; i < Count; i++)
{
var x = (float)i / (Count - 1); // smoothly goes across one axis
var z = Random.value; // randomly scatters on another
Vector3 Position = new Vector3( x * Width, 0, z * Depth);
// spawn something at Position
}

@Kurt-Dekker using that means you only spawn one object on each x coord, if you donâ€™t wanna use something complex like the poisson disk sampling i posted you can just divide the world to a grid and randomly spawn items in a random free cell.

the minimum distance is basically the cell size you use

Every method of randomness will end up with a different feel to the results. It is important to understand the implications of your choices. With sufficiently high density, the grid approach instantly becomes recognizable, especially with high-contrast very-regular items.

Then you start to have to put jitter, then the jitter has to know the bounds size MINUS the object size or else youâ€™ll have objects touching, etc., etc.

I was merely offering a trivial way to get more even coverage than random(x), random(y) approach.

Another approach, which is similar to the grid one, is to not have a specific number of objectsâ€”rather, a percentage of probability that they will be spawned. Then just iterate across each row of the grid and spawn if the probability is reached. The number of objects will vary, which might not be what you want, but it also lets you create a lot of different densities.

I did this in one project with creating a maze using horizontal and vertical wall units, so there was a probability in each dimension. This allowed a huge range of different maze densities, and you could have long corridors vertically or horizontally (set one probability high and the other low). I didnâ€™t check if it created â€śroomsâ€ť, because the player could shoot walls to get out if neededâ€¦also, it would be hard to check that

Oh man, good spot. Yes: to OP: you need to add the value that Instantiate() returns, which is the fresh one it created, otherwise all your list will have is X number of references to the same not-in-scene object, the prefab you started with.

public GameObject[] SpawnList = new GameObject[3];
public List<GameObject> objectsCreated = new List<GameObject>();
public int SpawnCount { get; set; }
// Update is called once per frame
private void Update()
{
if(SpawnCount <= 50)
{
var objectToSpawn = SpawnList[Random.Range(0, SpawnList.Length)];
var x = Random.Range(9,152);
var y = Random.Range(-1,3);
var pos = new Vector3(x, y, 0);
var newObject = Instantiate(objectToSpawn, pos, Quaternion.identity);
objectsCreated.Add(newObject);
SpawnCount++;
}
}
}