Search Unity

Help with PreFab Instantiation from a gameobject array

Discussion in 'Scripting' started by Collin__Patrick, Feb 7, 2016.

  1. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I keep getting an exception error:
    ArgumentException: The thing you want to instantiate is null.

    I am not sure why. Help is much appreciated.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class InstantiateCharacters : MonoBehaviour{
    5.  
    6.     //public int[] SelectedList = new int[10];
    7.     public static string[] characterNames = new string[] {"PlayerCharacter", "NamelessCharacterOne", "NamelessCharacterTwo",
    8.         "NamelessCharacterThree", "NamelessCharacterfour", "NamelessCharacterFive", "NamelessCharacterSix",
    9.         "NamelessCharacterSeven", "NamelessCharacterEight", "NamelessCharacterNine", "NamelessCharacterTen",
    10.         "NamelessCharacterEleven"};
    11.     public static GameObject[] characterPrefabs = new GameObject[32];
    12.  
    13.     public static void LoadSelectedCharacters(){
    14.         Debug.Log ("Loading Characters");
    15.         for (int i = 1; i<= 10; i++) {
    16.             Debug.Log ("Finding character " + i);
    17.             for (int k = 1; k <= characterNames.Length; k++) {
    18.                 Debug.Log ("Finding Character " + i + " Match");
    19.                 if (ArmyInformation.ActiveCharacters [i] == characterNames [k]) {
    20.                     Debug.Log ("Character Found " + characterNames [k]);
    21.                     Instantiate (characterPrefabs [k], new Vector3 (0, 3, 0), Quaternion.Euler (0, 0, 0));
    22.                     k = 1;
    23.                     Debug.Log ("Player Loaded");
    24.                 } else {
    25.                     Debug.Log (characterNames [k] + " Is not Character " + i);
    26.                 }
    27.             }
    28.         }
    29.     }
    30. }
     
  2. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    It looks like your characterPrefabs gameobject array is empty. You have created an array of length 32, but I don't see where it has been initialized or filled. When you try to instantiate using characterPrefabs [k], you get null because uninitialized arrays of reference types are filled with nulls.
     
  3. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    Does it manage to instantiate anything at all? Are you sure your characterPrefabs list is fully populated with prefabs? If there is an empty element in that list, then it's a straightforward error.

    Also make sure you aren't referencing some out of bounds index in your characterPrefabs list or something. Not sure, but it looks like sweeping from 1 to characterNames.Length would put you out of bounds at the end, because indeces go from 0 to (length-1).
     
  4. Gilmar

    Gilmar

    Joined:
    Dec 17, 2013
    Posts:
    30
    I believe line 17 should be changed from
    Code (csharp):
    1. for(int k =1; k <= characterNames.Length; k++){
    to

    Code (csharp):
    1. for(int k =1; k < characterNames.Length; k++){
     
  5. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I figured out the problem. I had populated the prefab array but changed it to static later, erasing the population. Now because the array is static I can no longer populate it. Is there a way I can populate a static array in the inspector?
     
  6. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    You can use a helper variable. Make the public list in that script such that it can be populated in the inspector, like you have. Then, perhaps in the Start() event, set the static list to the public list. Basically, you're just using one list to make inspector assignments, then immediately transferring the values in the list to the static list.
     
    Collin__Patrick likes this.
  7. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I did this. I am still getting the same error. What needs to be changed?

    Code (CSharp):
    1. public static GameObject[] characterPrefabs; //= new GameObject[characterNames.Length];
    2.     public GameObject[] Prefabs = new GameObject[32];
    3.     void Start(){
    4.         characterPrefabs = Prefabs;
    5.     }
     
  8. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    Have you tried printing the entire contents of characterPrefabs just before the instantiate statement in your first script just to be sure there are no single null entries for some reason?

    Are the two pieces of code you posted from the same script?
     
  9. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    Yes and yes.
     
  10. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    So then there are no null elements in your array printout, but you're still getting the null instantiate fault? Are you getting any out of array bounds errors?

    Also, just in case you didn't realize, the static array isn't necessary unless you want to reference the array from other classes. I realize you may be doing exactly that, but I just wanted to put that out there.
     
  11. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I have no other errors but I did some more tweaking and am now getting this error:
    NullReferenceException: Object reference not set to an instance of an object

    Also I have a level manager script using the method so it has to be static.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class InstantiateCharacters : MonoBehaviour{
    5.  
    6.     public static string[] characterNames = new string[] {"PlayerCharacter", "NamelessCharacterOne", "NamelessCharacterTwo",
    7.         "NamelessCharacterThree", "NamelessCharacterfour", "NamelessCharacterFive", "NamelessCharacterSix",
    8.         "NamelessCharacterSeven", "NamelessCharacterEight", "NamelessCharacterNine", "NamelessCharacterTen",
    9.         "NamelessCharacterEleven"};
    10.     public GameObject[] Prefabs = new GameObject[32];
    11.     public static GameObject[] characterPrefabs; //= new GameObject[characterNames.Length];
    12.  
    13.     void Start(){
    14.         characterPrefabs = Prefabs;
    15.     }
    16.  
    17.     public static void LoadSelectedCharacters(){
    18.         //characterPrefabs = Prefabs;
    19.         int x = 0;
    20.         Debug.Log ("Loading Characters");
    21.         for (int i = 1; i<= 10; i++) {
    22.             Debug.Log ("Character " + ArmyInformation.ActiveCharacters [i]);
    23.             for (int k = 1; k <= characterNames.Length; k++) {
    24.                 Debug.Log ("Finding Character " + ArmyInformation.ActiveCharacters [i] + " Match");
    25.                 if (ArmyInformation.ActiveCharacters [i] == characterNames [k]) {
    26.                     Debug.Log ("Character Found " + characterNames [k] + " Is " + ArmyInformation.ActiveCharacters [i]);
    27.                     Instantiate (characterPrefabs [k], new Vector3 (x, 3, 0), Quaternion.Euler (0, 0, 0));
    28.                     k = 1;
    29.                     x += 5;
    30.                     Debug.Log (ArmyInformation.ActiveCharacters [i] + " Loaded");
    31.                 } else {
    32.                     Debug.Log (characterNames [k] + " Is not Character " + ArmyInformation.ActiveCharacters [i]);
    33.                 }
    34.             }
    35.         }
    36.     }
    37. }
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class LevelController : MonoBehaviour {
    5.  
    6.     void Start(){
    7.         InstantiateCharacters.LoadSelectedCharacters ();
    8.     }
    9. }
     
  12. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    I might be missing something, but where are you filling "public GameObject[] Prefabs = new GameObject[32];"
    That array still looks empty to me.
     
  13. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    The inspector
     
  14. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    Ah sorry, I did miss that. It does look like you might have some index issues like Gilmar indicated. In both of your for loops you are starting at one which means that when you do something like:

    Code (CSharp):
    1. ArmyInformation.ActiveCharacters [i]
    you are actually starting at the second index position (ActiveCharacters[1]) instead of the first (ActiveCharacters[0]).

    I don't know what the length of that ActiveCharacters array is, but if it is 10, then you should be getting an index out of range error once i == 10. The same thing goes for the loop using characterNames.Length. characterNames.Length equals 12, but if you ever try to access characterNames[12], you will get an index out of range error.
     
  15. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    I mentioned this early on, actually. I still think it's a problem, but it doesn't seem to be directly causing the problem at hand... perhaps still related, though. OP isn't getting an out of bounds error yet because the script is crashing before we even get to that point. Once we fix the null instantiate issue, there will probably be an out of bounds fault.

    Have you tried printing characterPrefabs just after the assignment in Start(), instead of just before the Instantiate call? Are you sure nothing in another script is reinitializing this array somehow?
     
  16. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    I need to read through the comments more carefully I guess. Yeah, I don't really see how the index problem would cause the reported errors at this point. I actually set up a new project mimicking this one and populated the array in the inspector with a variety of prefabs. I used the same line of code that is used here to instantiate them and everything worked fine.

    Does the error indicate that it comes from this script? Is there instantiation happening somewhere else?
     
  17. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I am aware of the indexing issues. I am just trying to get results before I continue to tweak it any further so I know that it is at least working. I also know for a fact that no other scrips are interfering.
     
  18. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    Show me how you set it up in the Hierarchy/inspector. Maybe you did something different.
     
  19. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    I don't know if I fixed it or royally screwed it up. I put the controller and the Instantiate script on the same Game Object instead of different ones and now when I choose my characters and go to the next scene the entire engine freezes up. I am not sure what is happening but at least its results.
     
  20. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    This was the test. The prefabs array has everything assigned to it in the editor, then the start function assigns the non static array to the static characterPrefabs array and calls the InstantiatePrefabs method. The method uses the same instantiate code as yours and even spaces things 5 units apart. This is how it looked in the editor upon running it.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class InstantiateTest : MonoBehaviour
    4. {
    5.  
    6.     public GameObject[] prefabs = new GameObject[32];
    7.     public static GameObject[] characterPrefabs;
    8.  
    9.     void Start()
    10.     {
    11.         characterPrefabs = prefabs;
    12.         InstantiatePrefabs();
    13.     }
    14.  
    15.     void InstantiatePrefabs()
    16.     {
    17.         int x = 0;
    18.  
    19.         for (int i = 0; i < characterPrefabs.Length; i++)
    20.         {
    21.             Instantiate(characterPrefabs[i], new Vector3(x, 3, 0), Quaternion.Euler(0, 0, 0));
    22.             Debug.Log(characterPrefabs[i].name);
    23.             x += 5;
    24.         }
    25.     }
    26. }
     

    Attached Files:

  21. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    I had one other thought. It could be a script execution order problem. if you call that static LoadSelectedCharacters method from another class before the Start() on your InstantiateCharacters class has a chance to run, the characterPrefabs array will be empty and you will get a Null reference error.
     
  22. Hyblademin

    Hyblademin

    Joined:
    Oct 14, 2013
    Posts:
    725
    Good thinking... more print statements! See which runs first.
     
  23. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    When I changed the start method to Awake in the Instantiate script the entire thing froze up. I am assuming it is loading now. Any ideas on why it is freezing?
     
  24. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    Code (CSharp):
    1. for (int k = 1; k <= characterNames.Length; k++) {
    2.                 Debug.Log ("Finding Character " + i + " Match");
    3.                 if (ArmyInformation.ActiveCharacters [i] == characterNames [k]) {
    4.                     Debug.Log ("Character Found " + characterNames [k]);
    5.                     Instantiate (characterPrefabs [k], new Vector3 (0, 3, 0), Quaternion.Euler (0, 0, 0));
    6.                     k = 1;
    7.                     Debug.Log ("Player Loaded");
    8.                 } else {
    9.                     Debug.Log (characterNames [k] + " Is not Character " + i);
    10.                 }
    11.             }
    You might have an infinite loop here since k keeps getting reset to 1
     
  25. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    k gets reset once the correct character is found so when i increases k will be back to 1. This process should continue until all 10 characters are instantiated.
     
  26. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    As it is right now you compare strings here:

    Code (CSharp):
    1. if (ArmyInformation.ActiveCharacters [i] == characterNames [k])
    If the character is found, you instantiate it and then you set k back to 1.
    The problem is that when you do this, your i variable never gets incremented because the for loop using k never finishes.
    You just keep finding the same character over and over again.
    I'm pretty sure this is your problem, because an infinite loop will cause Unity to hang.

    what you probably need to do it replace k = 1; with break;
    And then fix your index out of range issues, because that will hit you next.
     
    Last edited: Feb 9, 2016
  27. Collin__Patrick

    Collin__Patrick

    Joined:
    May 20, 2015
    Posts:
    188
    Works perfectly. Thanks for the help
     
  28. Ahndrakhul

    Ahndrakhul

    Joined:
    Mar 7, 2015
    Posts:
    23
    I'm glad it's working. Good luck!