- Home /
How to randomly select a list index
I am writing a script to check spawn points and if there are no children attached i want to instantiate a child object onto it. So far so good the only problem I am currently having is picking a random index on my items list. It is called itemIndex
and is located inside the startSpawn()
.
what i have is int itemIndex = Random.Range (0,(objectsToSpawn.Count - 1));
and it seems to only ever pick the first item in the list.
Here is my code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
public class RespawnItems : MonoBehaviour {
public float restockTime;
[SerializeField]
private List<spawnPointInfo> spawnPoints = new List<spawnPointInfo>();
[SerializeField]
private List<objectSpawnInfo> objectsToSpawn = new List<objectSpawnInfo>();
private Terrain terrain;
private Transform thisTransform;
public float curTime;
[System.Serializable]
public struct objectSpawnInfo
{
public GameObject item;
}
[System.Serializable]
public struct spawnPointInfo {
public GameObject spawnPoint;
}
void Start() {
curTime = 0f;
thisTransform = transform;
}
void Update() {
curTime += Time.deltaTime;
if (curTime > restockTime) {
StartSpawn();
curTime = 0f;
}
}
void StartSpawn() {
for (int i = 0; i < spawnPoints.Count; i++) {
if (spawnPoints[i].spawnPoint.transform.childCount == 0 || spawnPoints[i].spawnPoint.transform.childCount == null) {
int itemIndex = Random.Range (1,(objectsToSpawn.Count - 1));
Spawn(spawnPoints[i].spawnPoint, objectsToSpawn[itemIndex].item);
}
}
}
void Spawn(GameObject sp, GameObject item) {
GameObject locObj = Instantiate (item).gameObject;
locObj.transform.position = new Vector3 (sp.transform.position.x, sp.transform.position.y, sp.transform.position.z);
Vector3 euler = locObj.transform.eulerAngles;
euler.y = Random.Range (0f, 360f);
locObj.transform.eulerAngles = euler;
if (locObj.GetComponent<SyncRotation> () != null) {
locObj.GetComponent<SyncRotation> ().rot = locObj.transform.rotation;
}
locObj.transform.parent = sp.transform;
if (Network.isServer) {
NetworkServer.Spawn (locObj);
}
}
}
Answer by NoseKills · Feb 01, 2017 at 05:06 PM
Your code says Random.Range (1,(objectsToSpawn.Count - 1));
. That will never return the first item in the list since indexing starts from 0.
This will return at minimum a value of 1 and at maximum a value of objectsToSpawn.Count - 2 (with 2 int parameters Random.Range only returns int values that are less than the second parameter).
It should be Random.Range (0, objectsToSpawn.Count);
if you want it to pick from all objects in the list.
Agree and up vote, i was going to say the exactly same thing.
ok i understand what you are saying. but doesn't indexing start at 0? so when i print out objectsToSpawn.Count
it says 2. so then Random.Range(0,2);
would return either 0,1 or 2 correct? so then if it picks 2 then objectsToSpawn[2].item
would return nothing because nothing is indexed at 2. is that correct or am i assu$$anonymous$$g wrong? ok well i guess i was assu$$anonymous$$g wrong. I went and changed it to what you have and bam seems to be working. Thank you so much for the help.
Nope. It's like i said in the answer. Random.Range(0,2);
returns either 0 or 1, never 2.
You can check it in the API docs (be sure to scroll down to the Random.Range(int, int) method. At the top of the page they explain the float version which works differently)
You are right that if objectsToSpawn.Count
is 2 and you try to get objectsToSpawn[2]
, it will be a problem, but ins$$anonymous$$d of "returning nothing" it will throw an error.
Thank you for expanding a little more on that for me and thank you for the link to the api docs i always forget to check there. gonna bookmark it now lol. thank you once again for all your help!!! much appreciated!