Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Setting Arrays: NullReferenceException: Object reference not set to an instance of an object

Discussion in 'Scripting' started by Dennooo, Nov 19, 2016.

  1. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    78
    Hi there,

    I get a typical null reference exception error, when I run the following code. Do one of you have an idea where the problem is? I can't figure out whats going wrong :/
    Thanks in advance.

    Code (CSharp):
    1. void OnLevelWasLoaded()
    2. {
    3.      PlayerData playerData = new PlayerData();
    4.  
    5.      playerData.mountSlotContent = new MountSlotContent[4];
    6.  
    7.       for (int i = 0; i < playerData.mountSlotContent.Length; i++)
    8.            {
    9.              // this is where I get the null ref error
    10.              playerData.mountSlotContent[i].slotContent = new int[3];
    11.             }
    12. }
    Code (CSharp):
    1. [System.Serializable]
    2. class PlayerData
    3. {
    4.     public MountSlotContent[] mountSlotContent;
    5. }
    6.  
    7. [System.Serializable]
    8. public class MountSlotContent
    9. {
    10.     public int[] slotContent;
    11. }
     
    Last edited: Nov 19, 2016
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    i < playerData.mountsSlotContent.Length
     
    Dennooo likes this.
  3. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    78
    Thanks! That was obviously wrong.
    I mistakenly forgot to paste that code from visual studio to this forum. I updated the first post.
    Since this was a pasting error, the problem still remains :(
     
  4. AndyGainey

    AndyGainey

    Joined:
    Dec 2, 2015
    Posts:
    216
    When you create your array of MountSlotContent, because MountSlotContent is a class and not a struct, you have four null references to MountSlotContent, rather than four actual instances of MountSlotContent. You need to instantiate a new MountSlotContent for each iteration inside your loop.

    Code (CSharp):
    1. void OnLevelWasLoaded()
    2. {
    3.     PlayerData playerData = new PlayerData();
    4.  
    5.     playerData.mountSlotContent = new MountSlotContent[4];
    6.  
    7.     for (int i = 0; i < playerData.mountSlotContent.Length; i++)
    8.     {
    9.         playerData.mountSlotContent[i] = new MountSlotContent();
    10.         playerData.mountSlotContent[i].slotContent = new int[3];
    11.     }
    12. }
     
    Dennooo likes this.
  5. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    78
    Thanks that already helped and the problem doesnt seem to appear anymore. But...in the grand scheme of related code another NULL REF problem appears. Let me elaborate on the context:
    I want a simple (local) save and load function. While the save function (the function in "OnLevelWasLoaded()", doesnt cause any problems, the Load() function causes now problems. Here is the full code:

    Code (CSharp):
    1. private string savingPath;
    2.  
    3. void Awake()
    4. {
    5.     Load();
    6. }
    7.  
    8. void OnLevelWasLoaded()
    9.     {
    10.          Save()
    11.     }
    12.  
    13. public void Save()
    14. {
    15.         BinaryFormatter bf = new BinaryFormatter();
    16.         FileStream file = File.Create(savingPath + "/playerData.dat");
    17.  
    18.         PlayerData playerData = new PlayerData();
    19.  
    20.         playerData.mountSlotContent = new MountSlotContent[4];
    21.  
    22.         for (int i = 0; i < playerData.mountSlotContent.Length; i++)
    23.             {
    24.                 playerData.mountSlotContent[i] = new MountSlotContent();
    25.  
    26.                 playerData.mountSlotContent[i].slotContent = new int[3];
    27.             }
    28.  
    29.         bf.Serialize(file, playerData);
    30.         file.Close();
    31. }
    32.  
    33. public void Load()
    34. {
    35.     if(File.Exists(savingPath + "/playerData.dat"))
    36.         {
    37.  
    38.             BinaryFormatter bf = new BinaryFormatter();
    39.             FileStream file = File.Open(Application.persistentDataPath + "/playerData.dat", FileMode.Open);
    40.             PlayerData playerData = (PlayerData)bf.Deserialize(file);
    41.             file.Close();
    42.  
    43.             // The problem appears here: Null Reference Exception: Object reference not set to an instance of an object
    44.             for (int i = 0; i < playerData.mountSlotContent.Length; i++)
    45.             {
    46.                  // do some loading stuff
    47.             }
    48.  
    49.     }
    50. }
    51.  
    52.  
    53. }
     
  6. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,139
    Your load is called from Awake and you are trying to access playerData.mountSlotContent. Does this actually have any value at this point? This is most likely the source of your null.
     
    Dennooo likes this.
  7. AndyGainey

    AndyGainey

    Joined:
    Dec 2, 2015
    Posts:
    216
    In general, when accessing data from an external source (in this case a file), don't trust anything, verify everything.

    In this case, after deserializing the file as a PlayerData instance, first check to see if playerData.mountSlotContent is null. Only access the Length property and go through the array after you've confirmed that there is indeed an array there, and not just a null reference. It may very well be the case that there is no array; maybe the file was tampered with, or perhaps the saved file is out of date from a time when the program did not guarantee that the array was not null.

    Now after that change, if the array is still coming back null, even after an earlier successful call to Save() with an array of 4 elements, the question becomes: Why does the serialization/deserialization process not seem to restore the array? If that's the case, I can't immediately see any problem that could explain such behavior. Your classes are properly marked as serializable, and you're just using the .NET serialization, rather than Unity's serialization system which has a lot of idiosyncrasies. Except I notice that you're using savingPath to save the file, and to check for the file's existance, but you're using Application.persistentDataPath to load the file. If those two paths differ, you might be constantly loading an old file with a null array, when the newer and correct file is sitting elsewhere never getting loaded.
     
    Dennooo likes this.
  8. Dennooo

    Dennooo

    Joined:
    May 12, 2015
    Posts:
    78
    Very embarassing, but the inconsistency between the savingPath and Application.persistentDataPath caused the null :/ Thanks a lot for pointing that out...I probably would have missed that for another couple of hours :)
     
  9. HeAdWi9H

    HeAdWi9H

    Joined:
    Jan 27, 2019
    Posts:
    2
    Even After 5 Years thanks for helping i had similar problem changed my class to struct and it worked :)