Instantiating prefabs from an array of GameObjects

Hi Everyone,

I’m new on here and also quite new to c# and Unity. Please be gentle with me if I’m asking a dumb question.

I was hoping for some help on something that is doing my head in. I am instantiating 2000 prefabs and have them rotate and move around the screen randomly. I have actually got the code working fine if I declare the prefab as global and drop the actual prefab onto the navigator window.

However this means it is always the same prefab floating about, but I want to put some different ones up into the air. I have created an array of prefabs and I am trying to assign one of the 22 different elements, randomly, to the instantiation. This is where the code falls down.

It is the line:

GameObject fragment = (GameObject) Instantiate(fragmentloadarray[iValue], position, Quaternion.Euler

that is causing the error: “NullReferenceException: Object reference to set to an instance of an object”

 void Start()
    {

        fragmentloadarray = new GameObject[22];
        fragmentloadarray = Resources.LoadAll("Fragments") as GameObject[];


        fragmentarray = new GameObject[numberOfFragments];

        for (int count = 0; count < numberOfFragments; count++)
        {

            Vector3 position = new Vector3(Random.Range(-sizeofarea, sizeofarea), Random.Range((-sizeofarea + 1.9f) / 1.4f, (sizeofarea + 1.9f) / 1.4f), Random.Range(-sizeofarea + 0.8f, sizeofarea + 0.8f));

            iValue = Mathf.RoundToInt(Random.Range(0.0f, 21.0f));

            GameObject fragment = (GameObject) Instantiate(fragmentloadarray[iValue], position, Quaternion.Euler
                  (
                    Random.Range(0.0f, 360.0f),
                    Random.Range(0.0f, 360.0f),
                    Random.Range(0.0f, 360.0f)
                  ));

            fragmentarray[count] = fragment;

            fragment.GetComponent<Rigidbody>().AddTorque(transform.up * Random.Range(-spinrate, spinrate));
            fragment.GetComponent<Rigidbody>().AddTorque(transform.right * Random.Range(-spinrate, spinrate));

            float scalefactortoapply = Random.Range(0.05f, 0.65f);
            Vector3 scale = fragment.transform.localScale;
            scale.Set(scalefactortoapply, scalefactortoapply, 0.1f);
            fragment.transform.localScale = scale;

            fragment.GetComponent<Rigidbody>().AddForce
                    (
                   Random.Range(-fragmentspeed, fragmentspeed),
                   Random.Range(-fragmentspeed, fragmentspeed),
                   Random.Range(-fragmentspeed, fragmentspeed)
                   );

        }
    }

I have been stuck on this for a few days now and would really appreciate some advice from the pro’s

Thanks in advance

Ian

Hello,
The null reference exception is coming because “fragmentloadarray” is empty.
The array is empty coz its unable to load from resource.
try to assign the array in inspector manually is possible.

Thanks

@uglymug ,below is a simple way you can manage something like this while keeping the legwork simple and rave via code instead of assigning an array yourself.

This code will automatically look for the file path you specify in the inspector and populate its list with available types.

using UnityEngine;
using System.Collections.Generic;

public class ArrayInstantiator : MonoBehaviour {

	[Header("Values")]
	public string resourcePath;
	public Transform spawnPosition;
	public int desiredCount;
	public float delayInterval;

	[Header("Debug")]
	public int currentCount;
	public List<GameObject> availableObjects = new List<GameObject>();

	void Start() {
		availableObjects.AddRange (Resources.LoadAll <GameObject> (resourcePath));
		InvokeRepeating ("SpawnObject", delayInterval, delayInterval);
	}

	void SpawnObject() {
		if (currentCount < desiredCount) {
			int spawnIdx = Random.Range (0, availableObjects.Count);
			GameObject inst = (GameObject)Instantiate (availableObjects[spawnIdx], spawnPosition.position, Quaternion.Euler (Vector3.zero));

			// Since we declared a local var of "inst" we can now have a reference
			// to this instantiated object and access its properties
		} else {
			CancelInvoke ("SpawnObject");
		}
	}
}

Note, the variables listed under the Debug header will be assigned via script so be sure to not set these values to anything yourself.

Heres some screenshots of the project folder and inspector to give you an idea of the setup:

https://gyazo.com/6214fb2c2e5bc4ba04d091d4a3507380

https://gyazo.com/8d21278290385fd5454f4ad93351bea7

You’ll see that in my Resources folder i created a SubFolder called "TestObjects" and put my items i want spawned in there, then in the spcripts inspector i assigned the Resource Path to "TestObjects/" as that follows the standard file-folder structure.

Now, you can assign all your logic to the temp variable "inst" inside of the SpawnObject function.

Let me know if you need any help with this.

Hi Guys,

thank you so much to everyone for the responses. The generosity in these forums always inspires me.

thanks especially @IronarmGames_LLC that’s an elegant solution. I did find an alternative bit of code (also using lists) that did work (after another 2 days of keyboard bashing). I’ve included it below in case anyone can make use of it but the solution you provided seems more elegant.

{

// Fragment behaviour

int numberOfFragments = 1600;
float spinrate = 0.000003f;
float fragmentspeed = 0.8f;
float sizeofarea = 2f;

void Start()
{

        // Get all Fragment prefabs (x22) from Fragments folder and create a list

        var loadedObjects = Resources.LoadAll("Fragments");
        List<GameObject> gameObjects = new List<GameObject>();
        foreach (var loadedObject in loadedObjects)
        {
            gameObjects.Add(loadedObject as GameObject);
        }


        for (int count = 0; count < numberOfFragments; count++)
        {

            //  Generate random start positions,  also calculates the bounds that the prefabs start within

            float actualxaxis = Random.Range(-xaxis/2, xaxis/2);
            float actualyaxis = Random.Range((-yaxis/2) + yoffset, (yaxis/2) + yoffset);
            float actualzaxis = Random.Range(-zaxis/2, zaxis/2);

            Vector3 position = new Vector3(actualxaxis, actualyaxis, actualzaxis);

            int pickfragment = Random.Range(0, 21);

            GameObject fragment = (GameObject)Instantiate(gameObjects[pickfragment], position, Quaternion.Euler
                  (
                    Random.Range(0.0f, 360.0f),
                    Random.Range(0.0f, 360.0f),                 // generate random orientations
                    Random.Range(0.0f, 360.0f)
                  ));

I’ve stripped out some lines that were not pertinent to the original question, hope it still makes sense.

thanks again everyone

Ian