2

I'm trying to save my game data. At the point of 'copy game data into serializable class objects' I'm having an issue. Here is my code:

public static void Save()
{
    // set save file
    .
    .

    // import game data to serializable class
    PlayerData data = new PlayerData();

    GameObject[] tiles = GameObject.FindGameObjectsWithTag("Tile");
    int i = 0;
    print (data.tiles.Length);  // prints as expected (initialization in constructor)
    foreach(GameObject tile in tiles)
    {
        data.tiles[i].X = tile.GetComponent<TileScript>().X;
        ^^^^^^^^^^^^^^^
        //null reference: object reference not set to an instance of object

        i++;
    }
    .
    .
    .
    print ("Game Saved!");
}

And here is the class I'm trying to save my game data into:

[Serializable]
class PlayerData
{
    public class Building
    {
        public int index;
    }
    public class Tile
    {
        public int X,Y;
        .
        .
    }

    public Tile[] tiles;

    public PlayerData()
    {
        tiles = new Tile[40];

    }
}

I cannot locate the mistake I make. Is there a special case with the [Serializable] class member initialization? Where do I make the mistake and how can I fix it?

Varaquilex
  • 3,447
  • 7
  • 40
  • 60
  • possible duplicate of [What is a NullReferenceException and how do I fix it?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – eddie_cat Nov 07 '14 at 16:55
  • 2
    You don't add anything to the tiles array, therefore data.tiles[i] returns null and thus fails to access the X member. – CodeSmile Nov 07 '14 at 16:55

1 Answers1

1

Each element of tiles is initialized to the default value of Tile. If Tile is a reference-type (i.e., a class rather than a struct), then it will be null. In addition to creating the array, you need to initialize each element to a new Tile object:

public Tile[] tiles;

public PlayerData()
{
    tiles = new Tile[40];
    for (int i = 0; i < tiles.Length; i++)
        tiles[i] = new Tile();
}

When you don't do this and you try to access the data at:

data.tiles[i].X

data.tiles[i] will return null. Attempting to access the X member on the null reference naturally throws your NullReferenceException.

Chris Sinclair
  • 22,858
  • 3
  • 52
  • 93
  • Rookie mistake. I think I need to refresh my C# reading. Thanks for pointing out. – Varaquilex Nov 07 '14 at 16:58
  • so what tiles = new Tile[40]; does – Milad Qasemi Nov 07 '14 at 16:59
  • @user2320445: It creates a `Tile[]` array with 40 `null` entries. That is: `tiles[0]` is `null`, `tiles[1]` is `null`, `tiles[39]` is `null`. Imagine if `Tile` didn't have a public parameterless constructor, or had several constructor overloads, what should `tiles = new Tile[40]` do to fill the elements? What if you didn't want to create _new_ `Tile` objects, but instead wanted to fill the array with _existing_ `Tile` objects you already had; does it make sense to do the work instantiating a bunch of `Tile` objects to fill the array just to throw them away? – Chris Sinclair Nov 07 '14 at 19:23