простое решение - цикл перебора рандомных варинтов X
// ВНЕ цикла подбора рандомного X для оптимизации
foreach (GameObject enemy in enemies)
{
// заполнить _usedCoordX
}
// цикл подбора рандомного X
while (true)
{
int x = Random.Range(1 - _minX, _maxX);
if (!_usedCoordX.Contains(x)) break;
}
(НЕ эффективное по перфомансу, можно оптимизить - структурами Spatial или заполненными областями - не буду приводить реализации)
___
UPDATE:
там где _usedCoordX заполняется
хорошо бы бить поле на GRID равномерный, аналог хеша
______
|__|__|
|__|__|
например
если позиция object.X >= 10 && object.X < 20 то newX=1
если позиция object.X >= 20 && object.X < 30 то newX=2
и т.п с шагом 10
тогда при уже существующем объекте с X = 15, не сгенерится объект с X = 16 или 17 и т.п т.к они в одной ячейке сетки
и Random конечно по той же размерности кидать (_maxX должен быть не полного пиксельного\объектого размера, а размера сетки)
UPD2: по теме
https://gamedev.stackexchange.com/questions/69310/...
и там же есть картинка
UPD3: вместо равномерного GRID - можно юзать истинный Collision Detection, т.е после генерации Random X - проверять всех врагов вокруг, и если есть - генерить заного, так наверное лучше будет
.. но опять же можно проверять по GRID-у всех в этой же ячейке (т.е если X равен 15, то проверим всех врагов - есть ли они в X от 10 до 19, и если нет - выход из цикла
.. плюс проверять в соседних ячейках (иначе будут прям вплотную генериться