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.

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

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.