- Home /
Instantiate random prefab from folder using Resources.LoadAll
Resources.LoadAll strikes me as an extremely versatile tool, and on the surface seems fairly easy to implement. However, I'm having a devil of a time putting together a straightforward "fill list with contents of this folder" function without getting some fairly frustrating errors.
I've found a good number of asset-specific solutions (i.e. for textures or sound files), but I'm sure I'm not the only one who would benefit from a straightforward guide on how to manage this with generic GameObjects.
I've tried a number of variations, but the sample below looks clean and straightforward enough to my eyes.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class RandomFromList : MonoBehaviour
{
public List<GameObject> roomList;
void Start ()
{
GenerateRoom ();
}
void GenerateRoom ()
{
roomList = Resources.LoadAll<GameObject>("Rooms");
GameObject roomToBuild = roomList [Random.Range (0, roomList.Count)];
GameObject newRoom = Instantiate (roomToBuild, transform.position, Quaternion.identity) as GameObject;
}
}
Most of my errors tend to be of the "cannot cast Object as GameObject" variety, implying that the LoadAll function is for some reason using Object data, and requires some (seemingly extraneous) casting to work. However, casting as GameObject and/or working with Objects yields similar errors - frustrating as I'm still trying to wrap my head around when and why Unity chooses to use Object at all.
Added confusion stems from the syntax for declaring and working with lists and arrays. While none of the systems for declaring these should be vastly different from each other, I regularly get error messages wherein Object[] has the array brackets. Since LoadAll seems perfect for lists given their easy resizability, it seems unlikely that the Unity framework would use an array at all in this context - is it just a complication of the [] around where I set the Random.Range (which has worked for me countless times in the past), or is this just a red herring?
"Array index out of range" crops up regularly thanks to the list in question remaining empty. For awhile I wondered if the list length might need to be set before it can be filled, but since I haven't seen this addressed in any of the other questions on this topic, I have to assume it's not the case. Still, worth mentioning just in case.
Again, I'm sure I'm not the only one to have this problem, and am certain there's someone out there with a workable solution they wouldn't mind sharing with the rest of us.
Answer by tanuj0092 · Oct 25, 2014 at 01:52 PM
Try this code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class RandomFromList : MonoBehaviour
{
public List<GameObject> roomList;
public GameObject[] roomListArray;
void Start ()
{
GenerateRoom ();
}
void GenerateRoom ()
{
//Store all Gameobjects in an array like this
roomListArray = Resources.LoadAll<GameObject>("Rooms");
//You can use ToList() function as you are using Linq
roomList = roomListArray.ToList();
GameObject roomToBuild = roomList [Random.Range (0, roomList.Count)];
GameObject newRoom = Instantiate (roomToBuild, transform.position, Quaternion.identity) as GameObject;
}
}
or you can use this reference
http://docs.unity3d.com/ScriptReference/Resources.LoadAll.html
However you can avoid ToList() conversion. You can play around array :)
That does not help. The conversion of a list into an array does indeed seem extraneous (and works no better), and using an array gives an invalid argument (float, float) error for Random.Range. Not sure why, as Random.Range can pick random objects off of a list no problem.
And please, give me a little credit. Script Reference is the first thing I checked, I wouldn't be posting here if the solution could be found there.
Hey, I did a little workaround on this code, I have edited the code as you cannot cast Object[] to GameObject[] directly. So, I put three prefabs in Rooms folder inside Resources folder in project window. I attached the script to an empty gameobject. And in this way I was able to instantiate the random object in the scene. Also, I named the objects randomly. I hope this would give you some help.
Answer by elmanofsuit · Oct 27, 2014 at 11:55 PM
Ah, figured it out. Turns out I had been (sometimes) casting correctly, but hadn't placed my folder inside of one called "Resources." Not sure why Unity never gave a "path not found" error, that could have certainly set me on the right track.
Technically that info is all in the Script Reference, but the way it's worded is a little unclear. I suppose some re-reading and guesswork could have saved me a lot of trouble, but at least this is a mistake I sure won't make again.