In general, if you do not want randoms throwing the same value twice, you implement a Shuffle Bag.
Here's the idea:
- Generate every possible outcome and store them in a list.
- Remove from list randomly until list runs out.
- Repeat.
Unlike what hobnob suggested, this can be done once in Awake()
or Start()
, is more efficient as you do not need to iterate through the entire list to check if the value has already been used every time you want a new random value, and will allow you to get random values during runtime as well with little overhead.
Here's an example:
//Initialize 2 lists
List<Vector3> shuffleBag = new List<Vector3>();
List<Vector3> shuffleBagBackup;
void Start()
{
//x,y,z range is define in these nested for loops
for (int x = -50; x < 10; x++)
{
for (int y = -10; y < 5; y++)
{
for (int z = -100; z < 20; z++)
{
shuffleBag.Add(new Vector3(x, y, z));
}
}
}
shuffleBagBackup = shuffleBag;
}
And whenever you want to get a new random position within your range, call this:
Vector3 GetRandomPos()
{
if (shuffleBag.Count == 1)
{
Vector3 pos = shuffleBag[0];
shuffleBag = shuffleBagBackup;
return pos;
}
int index = Random.Range(0, shuffleBag.Count);
Vector3 position = shuffleBag[index];
shuffleBag.RemoveAt(index);
return position;
}
Looking at the code that you've provided, you may also consider making the list a singleton and the GetRandomPos()
function static, should you need to access the random positions from multiple objects with this script.