Instantiating a list of gameobjects in Unity C#

GrayFur picture GrayFur · Jun 22, 2017 · Viewed 15.3k times · Source

How can I instantiate a list of GameObject in Unity3D using c#? I fill the list with prefabs manually in inspector window.

enter image description here

Below is the code I've written in Deck.cs, but I get "Object reference is not set to an instance of an object". If you have a solution with an array, that will be appreciated as well.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

namespace Assets
{
    class Deck:MonoBehaviour
    {
        public List<GameObject> deck;
        public void Fill()
        {
            GameObject c1 = Instantiate(deck[0]);
            GameObject c2 = Instantiate(deck[1]);
            GameObject c3 = Instantiate(deck[2]);
            GameObject c4 = Instantiate(deck[3]);
            GameObject c5 = Instantiate(deck[4]);
            GameObject c6 = Instantiate(deck[5]);
        }

    }
}

I also tried doing it with an array and I get 'The object you want to instantiate is null'

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

namespace Assets
{
    class Deck:MonoBehaviour
    {
        public GameObject card1;
        public GameObject card2;
        public GameObject card3;
        public GameObject card4;
        public GameObject card5;
        public GameObject card6;

        public GameObject[] deck;

        public void Start ()
        {
            deck = new GameObject[5];
            GameObject c1 = Instantiate(card1) as GameObject;
            GameObject c2 = Instantiate(card2) as GameObject;
            GameObject c3 = Instantiate(card3) as GameObject;
            GameObject c4 = Instantiate(card4) as GameObject;
            GameObject c5 = Instantiate(card5) as GameObject;
            GameObject c6 = Instantiate(card6) as GameObject;
        }

    }
}

Answer

Kardux picture Kardux · Jun 22, 2017

Well considering your comments and that the first script your provided works perfectly without any error (as it should: there's no reason it should return an error), I feel like you are very new to Unity.

Therefore I'd recommend you to look to the Unity tutorials before anything else (they are quite well made and will help you understand the basics of the engine). You can find the Roll-a-ball tutorial here.

About your question:

1- In the first script, the Fill() method isn't called anywhere, you have to do something like this:

private void Start()
{
    Fill();
}

2- This Start() method comes from the MonoBehaviour parent class (as well as the Update() method which is called every frame) and is called once at the beginning of the scene. Look to this chart to understand how unity flow is made.

3- Using a List<GameObject> or a GameObject[] all depends on your situation: if the size of the collection is going to change, go for a list. Otherwise array is advised.

4- Considering your script my guess is it should look like this:

namespace Assets
{
    class Deck : MonoBehaviour
    {
        [SerializeField]
        private GameObject[] deck;

        private GameObject[] instanciatedObjects;

        private void Start()
        {
            Fill();
        }

        public void Fill()
        {
            instanciatedObjects = new GameObject[deck.Length];
            for (int i = 0; i < deck.Lenght; i++)
            {
                instanciatedObjects[i] = Instanciate(deck[i]) as GameObject;
            }
        }
    }
}

You can of course still use lists if needed :)

EDIT:
If you want to use a list you simply have to:

  • change private GameObject[] instanciatedObjects; to private List<GameObject> instanciatedObjects;
  • replace instanciatedObjects = new GameObject[deck.Length]; by instanciatedObjects = new List<GameObject>();
  • replace instanciatedObjects[i] = Instanciated(deck[i]) as GameObject; by instanciateObjects.Add(Instanciated(deck[i]) as GameObject);

Hope this helps,