Instatiate at random point with for loop?

Hi all!

  1. I have 3 spawn points in the scene.
  2. I have the list of the objects to instatiate, they are 2 cubes and 1 sphere.
    How can I made to instatiate this 3 objects at random spaw points from the list???

I’ve started with this:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Test: MonoBehaviour {
	public List<GameObject> Holders = new List<GameObject>();
	public List<GameObject> Sticks = new List<GameObject>();
	
	void Start()
	{
		for (int i = 0; i < Holders.Count; i++)
		{
			for (int s = 0; s < Sticks.Count; s ++)
			{
				GameObject newStick = Instantiate(Sticks[s], Holders[i].transform.position, Quaternion.identity) as GameObject;
				Holders.RemoveAt(i);
				Sticks.RemoveAt(s);
			}
		}
	}
}

The problem is this instatiate only 2 objects at 2 positions, 1 of 3 spawnpoints and objects staying in the list and wont instatiate… Also I have no idea how to randomize instatiation… Any help?

You shouldn’t use RemoveAt in a for loop where you have chosen list.Count as the final. Perhaps a while loop.

while(Holders.count>0){
int h = Random.Range(0,Holders.Count-1);
int s = Random.Range(0,Sticks.Count-1);
GameObject newStick = Instantiate(Sticks[s], Holders[h].transform.position, Quaternion.identity) as GameObject;
  Holders.RemoveAt(h);
 Sticks.RemoveAt(s);

}

This is not a correct way to iterate through list: List<T>.RemoveAt(Int32) Method (System.Collections.Generic) | Microsoft Learn
In every iteration you remove elements from the list and as doc states the remaining elements get renumbered. So you have elements 0:A 1:B and 2:C. In your loop you instantiate first element A and remove it from list. Now you have list: 0:B 1:C but your for index is 1 by now so you skip element B.
You should iterate through list and remove elements only after you are done instantiating all of them.
Also I’m not sure that List is always numbered from 0 onwards (you should make sure). You might want to use foreach metchod List<T>.ForEach(Action<T>) Method (System.Collections.Generic) | Microsoft Learn instead of assuming indexes.

EDIT: what fire7side suggested is good and easier to implement

For randomizing: Unity - Scripting API: Random

Thanks guys, will give it a try.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Fate : MonoBehaviour {
	public List<GameObject> Holders = new List<GameObject>();
	public List<GameObject> Sticks = new List<GameObject>();
	
	void Start()
	{
	    while(Holders.Count>0)
		{
		    int h = Random.Range(0,Holders.Count-1);
		    int s = Random.Range(0,Sticks.Count-1);
		    GameObject newStick = Instantiate(Sticks[s], Holders[h].transform.position, Quaternion.identity) as GameObject;
		    Holders.RemoveAt(h);
		    Sticks.RemoveAt(s);
		}
	}
}

This works well

Only if you’re lucky :slight_smile:

You iterate through all elements of Sticks list but then you pick a random element of that list to instantiate so some elements will get instantiated multiple times, other not at all.

You should iterate through things to instantiate and instantiate them one by one and pick randomly one of the spawn points every time you instantiate an element. Spawn point random but not what you are spawning. You want instantiate all of elements not a random selection.

you don’t need to loop over all the holders. if I assume the holders are the spawn points. just loop through your objects list and spawn them at a random holder/spawn point.

public List<GameObject> Spawners = new List<GameObject>();
public List<GameObject> Sticks = new List<GameObject>();

void Start () {

	// loop through the sticks and instantiate each on a random
	// spawn point / holder in your code
	foreach(GameObject g in Sticks) {
	
		int r = Random.Range(0, Spawners.Count - 1);
		
		Instantiate (g, Spawner[r].transform.position, Quaternion.identity);
}

unless you want to spawn all objects on every spawn point. then this

public List<GameObject> Spawners = new List<GameObject>();
public List<GameObject> Sticks = new List<GameObject>();

void Start () {

	// loop through the spawners / holders
	for(int i = 0; i < Spawners.Count; i++) {
	
		// loop through the sticks and instantiate each on a random
		// spawn point / holder in your code
		foreach(GameObject g in Sticks) {
		
			int r = Random.Range(0, Spawners.Count - 1);
			
			Instantiate (g, Spawner[r].transform.position, Quaternion.identity);
	}
}

He said the while loop worked. It only iterates over the remaining elements, after the ones used were removed. So it’s not luck. It’s mathematics. When you get to the last one, it just takes it because there are no other choices. The list gets shorter each iteration. It’s completely impossible for an element to get instantiated multiple times and all will be used.

friedfish, in both your code examples, 2 or more objects could get spawned in the same location, and because the loops are nested in the second, you would create nine objects.

Yep, while loop works ok, the only thing here to adjust is

int h = Random.Range(0,Holders.Count-1);
int s = Random.Range(0,Sticks.Count-1);

for

int h = Random.Range(0,Holders.Count);
int s = Random.Range(0,Sticks.Count);

Otherwise it seems to not use one of the spawnpoint for randomisation