- Home /
Spawning random object at predefined locations
Hello,
I searched around and found different pieces of code that even though separately cover all parts of my problem, when put together are not working..
Here is what I need to do :
I have 14 spawn points located on my terrain.
I have 14 game objects to spawn.
What I need is to spawn one object (chosen at random, let's say Number3 from gameobject list) at spawn point Nr1 (spawn points can be iterated based on their number)
Next iteration is to choose again a new object from the updated gameobject list(the gameobject list, minus Number3 which was previously spawned) and spawn it at spawn point Nr2
Iterations continue until all objects are uniquely spawned on all the spawn points.
I need this for my game world map, where the objects will represent loading triggers for the respective scenes.
Help is very much appreciated as I am still a newbie in scripting. Thank you.
Answer by Chronos-L · Jun 03, 2013 at 11:12 AM
One way to do it is to shuffle the spawn point array, then you can do something like this:
for( int i = 0; i < spawnPoints.length; ++i ) {
/*Spawn gameObjectArray[i] at spawnPoints[i];*/
}
To do a shuffle, you can go for a Fisher–Yates shuffle:
Transform [] myArray = ...;
int i = myArray.length;
while( --i >= 0 ) {
int randIndex = Random.Range( 0, myArray.length );
//Swap i with a random index
Transform temp = myArray[i];
myArray[i] = myArray[randIndex];
myArray[randIndex] = temp;
}
If you are using a collection to store the spawn points, then you can go for this:
List<Transform> spawnPoints = ...;
//You can use either collections or array to store the spawned object, it doesn't matter
GameObject[] spawnThis = ...;
...
for( int i = 0; i < spawnThis.Length; ++i ) {
int randIndex = Random.Range( 0, spawnPoints.Count );
Transform sp = spawnPoints[randIndex];
spawnPoints.RemoveAt( randIndex );
/*Spawn spawnThis[i] at sp*/
}
Ok, I'm using the second piece of code. I'm creating the list and even though it says there are 14 objects in it, this part is giving me different, numbers of objects.
int randIndex = Random.Range( 0, spawnPoints.Count );
Transform sp = spawnPoints[randIndex];
spawnPoints.RemoveAt( randIndex );
Each time I restart the game it shows : 3,1,5 etc (a random number of spawnpoints)
How to modify it so that I have the maximum 14 objects ?
3,1,5 were the values of which variable? spawnPoints.Count
or randIndex
?
I mean the number of spawn points (3 spawn points, 1 spawn point, 5 spawn points etc)
Let's take the case when 5 spawnpoints were shown, indeed they were set randomly in the list, but they were only 5 ins$$anonymous$$d of 14.
This is my code :
public class World$$anonymous$$apRandomizer : $$anonymous$$onoBehaviour {
public List<Transform> spawnPoints ;
public int sizeOfList;
public GameObject[] spawnThis;
// Use this for initialization
void Start () {
Invoke("Generate", 0);
}
// Update is called once per frame
void Update () {
}
void Generate()
{
GameObject[] go = GameObject.FindGameObjectsWithTag("BattlePointSpawner");
foreach(GameObject BP in go)
Addtarget(BP.transform);
}
public void Addtarget(Transform BP)
{
spawnPoints.Add(BP);
sizeOfList = spawnPoints.Count;
Invoke("Spawn", 0);
}
void Spawn()
{
for( int i = 0; i < spawnThis.Length; ++i )
{
Debug.Log (sizeOfList);
int randIndex = Random.Range( 0, sizeOfList );
Transform sp = spawnPoints[randIndex];
spawnPoints.RemoveAt( randIndex );
}
}
}
Error that give me after I run the game : ArgumentOutOfRangeException: Argument is out of range. Parameter name: index System.Collections.Generic.List`1[UnityEngine.Transform].get_Item (Int32 index) (at /Applications/buildAgent/work/b59ae78cff80e584/mcs/class/corlib/System.Collections.Generic/List.cs:633) World$$anonymous$$apRandomizer.Spawn () (at Assets/$$anonymous$$yScripts/World$$anonymous$$apRandomizer.cs:42)
Let me show you how I will do it, and you can compare it to your code and see what's the difference between $$anonymous$$e and yours.
Code not tested
public Transform[] spawnPoints;
public GameObject[] spawnThese;
void Start() {
//I get these from Google, they should work
//If not, just google for "C# convert array to list" or ".NET convert array to list"
List<Transform> sp = spawnPoints.ToList();
List<Transform> sp = new List<Transform>( spawnPoints );
if( spawnThese.length <= spawnPoints.length ) { //Only spawn when there are enough spawnPoints
for( int i = 0; i < spawnThese.length; ++i ) {
int randIndex = Random.Range( 0, sp.Count );
Transform selectedPoint = sp[randIndex];
sp.RemoveAt( randIndex );
/*Spawn spawnThese[i] at selectedPoint*/
}
}
}
If you don't $$anonymous$$d, have you give the first approach a shot?
Answer by Mahtrok · Jun 03, 2013 at 06:55 PM
for( int i = 0; i < spawnThis.Length; ++i )
{
Debug.Log (sizeOfList);
int randIndex = Random.Range( 0, sizeOfList );
Transform sp = spawnPoints[randIndex];
spawnPoints.RemoveAt( randIndex );
}
You are changing the values inside your list during the loop, so that your sizeOfList != spawnPoints.Count. If your Random,Range then tries to get the spawnPoint from 0 to sizeOfList it may get an index of your list no longer existing ( sizeOfList == 14, spawnPoints.Count == 13 ) which ends up in a null reference exception. You should not Remove the spawnPoint inside the loop OR you should simply reduce your sizeOfList after RemoveAt by 1 as well.
Greetz
Hey $$anonymous$$ah,, Thanks for the input. Indeed I realized I was doing it wrong.
Here is my code now which iterates correctly :
public class World$$anonymous$$apRandomizer : $$anonymous$$onoBehaviour {
public List<Transform> spawnPoints ;
public int sizeOfList;
public GameObject[] spawnThis;
public List<Transform> prefabTransforms;
// Use this for initialization
void Start () {
Invoke("Generate", 0);
}
// Update is called once per frame
void Update () {
}
void Generate()
{
GameObject[] go = GameObject.FindGameObjectsWithTag("BattlePointSpawner");
foreach(GameObject BP in go)
Addtarget(BP.transform);
}
public void Addtarget(Transform BP)
{
spawnPoints.Add(BP);
sizeOfList = spawnPoints.Count;
Invoke("RandomizeBuiltinArray", 0);
}
void RandomizeBuiltinArray()
{
prefabTransforms = new List<Transform>();
for (var i = spawnPoints.Count - 1; i >= 0; i--) {
var r = Random.Range(0,i);
var tmp = spawnPoints[i];
spawnPoints[i] = spawnPoints[r];
spawnPoints[r] = tmp;
Transform sp = spawnPoints[r];
prefabTransforms.Add(Instantiate(spawnThis[i].transform, sp.position , sp.rotation) as Transform);
print(spawnPoints[r]);
}
}
}
Now I;m at the second part of the problem. I spawn the objects but I spawn all the objects from the spawnThis list for eact object from spawnPoints list, so I get like 14 times more spawns..
Ok, so I remove the :
prefabTransforms.Add(Instantiate(spawnThis[i].transform, sp.position , sp.rotation) as Transform);
and call it from where ? How do I call it ? Please help.
@primus88 you need to try to do this yourself. This is not a forum for people to hold your hand every step of the way. If you want to learn this you need to spend at least a few $$anonymous$$utes thinking it through.
Try this: it spawns every Object of your array spawnThis once at a unique spawnpoint.
void Generate () {
GameObject[] go = GameObject.FindObjectsWithTag ("BattlePointSpawner");
// Add all BP transforms
foreach( GameObject BP in go ) {
AddTarget ( BP.transform );
}
// Spawn all objects at a unique spawnpoint and each Object only once
for ( int i = 0; i < spawnThis.Length; i++) {
RandomizeBuiltInArray (i);
}
}
void AddTarget ( Transform t ) {
spawnPoints.Add ( t );
}
void RandomizeBuiltInArray ( int index ) {
int r = Random.Range(0, spawnPoints.Count-1);
Instantiate(spawnThis[index], spawnPoints[r].position, spawnPoints[r].rotation) as Transform;
spawnPoints.RemoveAt(r);
}
Thank you.
For this line : Instantiate(spawnThis[index].transform, spawnPoints[r].position, spawnPoints[r].rotation) as Transform;
I receive this error :
World$$anonymous$$apRandomizer.cs(75,107): error CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement
Your answer
Follow this Question
Related Questions
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Player spawn after touching 0 Answers
Spawning script error 0 Answers
Unity Engine issue... 1 Answer
random spawn locations.... 2 Answers