- Home /
I made this script to instantiate objects, but when the game starts I get this error:IndexOutOfRangeException: Array index is out of range.
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class TileManager : MonoBehaviour {
public GameObject[] tilePrefabs;
public GameObject currentTile;
private static TileManager instance;
private Stack<GameObject> leftTiles = new Stack<GameObject>();
private Stack<GameObject> topTiles = new Stack<GameObject>();
private Stack<GameObject> rightTiles = new Stack<GameObject>();
public static TileManager Instance
{
get
{
if (instance == null)
{
instance = GameObject.FindObjectOfType<TileManager> ();
}
return instance;
}
}
public Stack<GameObject> LeftTiles
{
get
{
return leftTiles;
}
set
{
leftTiles = value;
}
}
public Stack<GameObject> TopTiles
{
get
{
return topTiles;
}
set
{
topTiles = value;
}
}
public Stack<GameObject> RightTiles
{
get
{
return rightTiles;
}
set
{
rightTiles = value;
}
}
// Use this for initialization
void Start ()
{
CreateTiles (30);
for (int i = 0; i < 15; i++)
{
SpawnTiles ();
}
}
// Update is called once per frame
void Update () {
}
public void CreateTiles (int amount)
{
for (int i = 0; i < amount; i++)
{
LeftTiles.Push (Instantiate (tilePrefabs [0]));
TopTiles.Push (Instantiate (tilePrefabs [1]));
RightTiles.Push (Instantiate (tilePrefabs[2]));
TopTiles.Peek ().name = "TopTile";
TopTiles.Peek ().SetActive (false);
LeftTiles.Peek ().name = "LeftTile";
LeftTiles.Peek ().SetActive (false);
RightTiles.Peek ().name = "RightTile";
RightTiles.Peek ().SetActive (false);
}
}
public void SpawnTiles()
{
if (LeftTiles.Count == 0 || TopTiles.Count == 0 || RightTiles.Count == 0)
{
CreateTiles (15);
}
//Generating a random number between 0 and 1
int randomIndex = Random.Range (0, 3);
if (randomIndex == 0)
{
GameObject tmp = LeftTiles.Pop ();
tmp.SetActive (true);
tmp.transform.position = currentTile.transform.GetChild (0).transform.GetChild (randomIndex).position;
currentTile = tmp;
}
else if(randomIndex == 1)
{
GameObject tmp = TopTiles.Pop ();
tmp.SetActive (true);
tmp.transform.position = currentTile.transform.GetChild (0).transform.GetChild (randomIndex).position;
currentTile = tmp;
}
else if (randomIndex == 2)
{
GameObject tmp = RightTiles.Pop();
tmp.SetActive(true);
tmp.transform.position = currentTile.transform.GetChild(0).transform.GetChild(randomIndex).position;
currentTile = tmp;
}
currentTile = (GameObject)Instantiate (tilePrefabs[randomIndex], currentTile.transform.GetChild (0).transform.GetChild (randomIndex).transform.GetChild(randomIndex).position, Quaternion.identity);
}
}
Doesn't the error tell you what line it's happening on?
Answer by Graphics_Dev · Jan 24, 2016 at 11:06 PM
Line 110 should be:
int randomIndex = Random.Range (0, tilePrefabs.Length);
You only check for 0, 1, and 2 so at line 133 you use tilePrefabs[randomIndex] which probably only has a length of 3.
Let me know if this helps ;)
Thanks for the corrective comments I voted you each up :)
Safer to do this, you'll never be wrong this way. =)
Random.Range (0, tilePrefabs.Length);
If using floats: "Returns a random float number between and $$anonymous$$ [inclusive] and max [inclusive] (Read Only)."
If using ints: "Returns a random integer number between $$anonymous$$ [inclusive] and max [exclusive] (Read Only)."
source: http://docs.unity3d.com/ScriptReference/Random.Range.html
So you do not need to -1 from the length.
Sorry, didn't know max was exclusive for ints ;)
It's one of those things that lingers with us all from C++, just wanted to clarify for the OP.
If there are no tilePrefabs size is 0,
"If max equals $$anonymous$$, $$anonymous$$ will be returned. The returned value will never be max unless $$anonymous$$ equals max."
$$anonymous$$in will be 0 and max will be 0, therefore $$anonymous$$ = max, therefore the returned value will be 0 which will raise an error because 0 will be out of range.
If a randomly selected slot does not have an assigned prefab,
you will raise a null exception (the object you are trying to access is null)...
to check for these two potential errors put this in your start function:
// check if length is 0 to avoid out of range exception
if (tilePrefabs.Length == 0) {
Debug.LogError ("No tilePrefabs are assigned!");
}
// check if all slots are filled
for (int i = 0; i < tilePrefabs.Length; i++){
if (tilePrefabs[i] == null) {
Debug.LogError ("$$anonymous$$issing tilePrefab!");
}
}