- Home /
Random Positions without Repeating
Hi everyone, i want my objects to spawn at random positions without repeating the same position. For example there are 7 locations and and i basically want them to shuffle.
I tweaked the Spawner script that is used in the 2D Platformer demo to have random spawns. It is below. Any idea how can to avoid repeating?
using UnityEngine;
using System.Collections;
public class SpawnerMY : MonoBehaviour
{
public float spawnTime = 5f; // The amount of time between each spawn.
public float spawnDelay = 3f; // The amount of time before spawning starts.
public GameObject[] enemies; // Array of enemy prefabs.
public Transform[] teleport;
void Start ()
{
// Start calling the Spawn function repeatedly after a delay .
InvokeRepeating("Spawn", spawnDelay, spawnTime);
}
void Spawn ()
{
// Instantiate a random enemy.
int enemyIndex = Random.Range(0, enemies.Length);
int tele_num = Random.Range(0,7);
Instantiate(enemies[enemyIndex], teleport[tele_num].position, teleport[tele_num].rotation);
// Play the spawning effect from all of the particle systems.
foreach(ParticleSystem p in GetComponentsInChildren<ParticleSystem>())
{
p.Play();
}
}
}
Create a list of int's, then select a random item from the list then remove it. If you need a script example let us known.
Well i tried to achieve something like that and came up with the code down below. But it still repeats so i have kinda no idea what to do.
// Public so you can fill the array in the inspector
public Transform[] scenarios;
public float spawnTime = 5f; // The amount of time between each spawn.
public float spawnDelay = 3f; // The amount of time before spawning starts
public GameObject[] enemies; // Array of enemy prefabs.
void Start ()
{
// Start calling the Spawn function repeatedly after a delay .
InvokeRepeating("Spawn", spawnDelay, spawnTime);
}
void Spawn ()
{
Shuffle (scenarios);
// Instantiate a random enemy.
int enemyIndex = Random.Range(0, enemies.Length);
int tele_num = Random.Range(0, scenarios.Length);
Instantiate(enemies[enemyIndex], scenarios[tele_num].position, scenarios[tele_num].rotation);
// Play the spawning effect from all of the particle systems.
foreach(ParticleSystem p in GetComponentsInChildren<ParticleSystem>())
{
p.Play();
}
}
void Shuffle(Transform[] a)
{
// Loops through array
for (int i = a.Length-1; i > 0; i--)
{
// Randomize a number between 0 and i (so that the range decreases each time)
int rnd = Random.Range(0,i);
// Save the value of the current i, otherwise it'll overright when we swap the values
Transform temp = a[i];
// Swap the new and old values
a[i] = a[rnd];
a[rnd] = temp;
}
// Print
for (int i = 0; i < a.Length; i++)
{
Debug.Log (a[i]);
}
}
Well your shuffling each time, and then selecting a random item from a random list, so it will stay random. :)
You need to Shuffle first in your Start, store a private int that starts at 0, then increase this after each spawn, when this gets to your lists count, reset back to 0, and optionally reshuffle.
Answer by fafase · Oct 15, 2014 at 03:53 PM
[SerializeField] private int range = 20; // Hom many items you want, will show in Inspector
List<int>list = new List<int>();
void Start()
{
FillList();
}
void FillList()
{
for(int i = 0; i < range; i++)
{
list.Add(i);
}
}
int GetNonRepeatRandom()
{
if(list.Count == 0){
return -1; // Maybe you want to refill
}
int rand = Random.Range(0, list.Count);
int value = list[rand];
list.RemoveAt(rand);
return value;
}
How can i connect the value int to the void Spawn(). I tried the code below but didnt work as i expected. How can i fix it?
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ShuffleList : $$anonymous$$onoBehaviour {
// Public so you can fill the array in the inspector
public Transform[] scenarios;
public float spawnTime = 5f; // The amount of time between each spawn.
public float spawnDelay = 3f; // The amount of time before spawning starts
public GameObject[] enemies; // Array of enemy prefabs.
[SerializeField] private int range = 20; // Hom many items you want, will show in Inspector
List <int> list = new List<int> ();
void Start()
{
InvokeRepeating("Spawn", spawnDelay, spawnTime);
FillList();
}
void FillList()
{
for(int i = 0; i < range; i++)
{
list.Add(i);
}
}
int GetNonRepeatRandom()
{
if(list.Count == 0){
return -1; // $$anonymous$$aybe you want to refill
}
int rand = Random.Range(0, list.Count);
int value = list[rand];
list.RemoveAt(rand);
return value;
}
void Spawn ()
{
// Instantiate a random enemy.
int enemyIndex = Random.Range(0, enemies.Length);
//int tele_num = Random.Range(0, scenarios.Length);
Instantiate(enemies[enemyIndex], scenarios[value].position, scenarios[value].rotation);
}
}
int enemyIndex = GetNonRepeatRandom();
But remember what do you want to happen when all random positions have be used, if you want to randomize again, just put fillList() in the line that says return -1;
Answer by Eno-Khaon · Oct 14, 2014 at 06:19 PM
One possible solution would be to use a List for the positions to place them. http://answers.unity3d.com/questions/284054/lists-c.html
You can populate the list when ready to use it, then remove the specific entries from it as you use them. That way, you could randomly choose a position from the List and never have to worry about repeating.
Answer by Maynk · Dec 14, 2020 at 12:25 PM
Don't Take An Effort, Do Easier in Unity C#
//Random.Range Position But Not Repeat
{
public GameObject spawnEnmy;
public List<Transform> spnPosns = new List<Transform>();
//Queue<Transform> spnPnts = new Queue<Transform>();
float spnIn, spwnOut;
private void Awake() => spnIn = spnPosns.Count;
private void Start()
{
while (spwnOut <= (int)spnIn)
{
if (spnPosns.Count >= 0)
{
var rdmNxt = spnPosns[Random.Range(0, spnPosns.Count)];
spwnIng(spawnEnmy, rdmNxt);
spnPosns.Remove(rdmNxt);
}
spwnOut++;
Debug.Log(spnPosns.Count);
}
}
public static void spwnIng(GameObject spwnObj, Transform spwnPos) => Instantiate(spwnObj, spwnPos.position, Quaternion.identity);
}
When You Run on Unity Do Work fine But in the Last "ArgumentOutOfRangeException" Don't penic Because Index List<> Size will Zero, This Not A Coding this are Debug Mistake Because Debug Skip if() condion in this, Anyway Because code in Start() So Not Wrong with Them