Save load custom class values not assigned object null reference

Okay, so in short, this is my first time trying to create save file codes and custom classes in unity, and the guides I am following does not provide all the data I need to figure out how to continue.

What I am trying to do is to, simply put, press a gui button, and that should set some variables from a custom script to a hard-coded value (this is just for testing, the values are meant to be some form of user input, either buttons or a text field) and save these values. Now, when I press my gui button, I get the error “reference Null Reference Exception: Object reference not set to an instance of an object”.

I am probably doing a whole world of hurt with errors I cannot see here but this is the lines of code that unity points out as problems:

DemographicData.Completed.TD.Age = 20;
DemographicData.Completed.TD.Gender = “Kvinde”;
DemographicData.Completed.TD.AlreadyCompletedThis = true;

If I outcomment those three lines, unity stop complaining.

And this is the relevant code pieces:

Custom class script 1)

using UnityEngine;
using System.Collections;

[System.Serializable]
public class TestData{

	public bool AlreadyCompletedThis;
	public int Age;
	public string Gender;

	public TestData(){
		this.Age = 0;
		this.Gender = "";
		this.AlreadyCompletedThis = false;
	}
}

Custom class 2

[System.Serializable]
public class DemographicData{
	public static DemographicData Completed;
	public TestData TD;
	public DemographicData(){
		TD = new TestData ();
	}
}

The relevant code from the GUI script

if (GUI.Button (new Rect ((Screen.width * 0.5f) - (SWdNoB * 3f * 0.5f), (Screen.height * 0.5f), SWdNoB * 3f, BoxHeight), "I'm filling out data")) {
	DemographicData.Completed.TD.Age = 20;
	DemographicData.Completed.TD.Gender = "Male";
	DemographicData.Completed.TD.AlreadyCompletedThis = true;
	SaveLoad.SaveTestData ();
	ContinueOnToMenu = true;
}

The not so relevant save script, but just in case something is wrong here

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public static class SaveLoad {

	public static List<DemographicData> GameTestData = new List<DemographicData>();
	public static void SaveTestData(){
		SaveLoad.GameTestData.Add (DemographicData.Completed);
		BinaryFormatter bf = new BinaryFormatter ();
		FileStream file = File.Create (Application.persistentDataPath + "/GameTestData.gd");
		bf.Serialize (file, SaveLoad.GameTestData);
		file.Close ();
	}
	public static void LoadTestData (){
		if (File.Exists (Application.persistentDataPath + "/GameTestData.gd")) {
			BinaryFormatter bf = new BinaryFormatter ();
			FileStream file = File.Open (Application.persistentDataPath + "/GameTestData", FileMode.Open);
			SaveLoad.GameTestData = (List<DemographicData>)bf.Deserialize (file);
			file.Close ();
	}
}

}

If it matters anything, The custom class “DemographicDate” is placed in the SaveLoad script, although it has been placed outisde everything.

I hope this is enough information to get the help I need, I normally love to figure these things out for myself, but I am lacking the time to do so.

Thanks in advance :slight_smile:

So I foudn out that I called my list before I created it, and that I did not create the lists I though I was creating.

I solved the problem by putting a statement into the load function telling it that if there were no list, then create one, and in the gui script, I called the load function before trying to stuff things into it.

If someone somehow get the same error, this is my now changed code:

Custom class 1

(the same)

custom class 2

[System.Serializable]
public class DemographicData{
	*(deleted line)*
	public TestData TD;
	public DemographicData(){
		TD = new TestData ();
	}
}

Gui script code

void OnGUI () {

	/*(...)*/

		if (!StartWasPressed) {
			if (GUI.Button (new Rect (/*...*/), "Start")) {
				SaveLoad.LoadTestData (); /*(This is where I make a list if there is none)*/
				StartWasPressed = true;
			}
		}
		if (StartWasPressed) {
			ContinueOnToMenu = SaveLoad.GameTestData [0].TD.AlreadyCompletedThis;
			if (GUI.Button (new Rect (...), "Quit")) {
				Application.Quit ();
			}
			if (!ContinueOnToMenu) {

				if (DemographicsDataFilledOut [0]) { //age, gender, occupation
					//age
					GUI.Box(new Rect(/*...*/), "Please select your 

age range");
if (GUI.Button(new Rect(…)," - 15")){
/(…)/
SaveLoad.GameTestData [0].TD.Age = 1;
DataFieldMarkedCorrectly [0] = true;
}

					/*(...)*/

					if (GUI.Button (new Rect (/*...*/),"Continue")) {
						if (/*all data filled out == true*/) {
							SaveLoad.SaveTestData ();
							DemographicsDataFilledOut [0] = false;
							DemographicsDataFilledOut [1] = true;
						}
					}

					/*(...)*/
				}
				/*(...)*/
			}

and the now very relevant save load script

using UnityEngine;
using System.Collections;
using System.Collections.Generic; //This allows for dynamic lists
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public static class SaveLoad {

	public static List<DemographicData> GameTestData = new List<DemographicData>();
	public static void SaveTestData(){
		BinaryFormatter bf = new BinaryFormatter ();
		FileStream file = File.Create (Application.persistentDataPath + "/GameTestData.gd");
		bf.Serialize (file, SaveLoad.GameTestData);
		file.Close ();
	}
	public static void LoadTestData (){
		if (File.Exists (Application.persistentDataPath + "/GameTestData.gd")) {
			BinaryFormatter bf = new BinaryFormatter ();
			FileStream file = File.Open (Application.persistentDataPath + "/GameTestData.gd", FileMode.Open);
			SaveLoad.GameTestData = (List<DemographicData>)bf.Deserialize (file);
			file.Close ();
		} else { /*(This is where I make sure that a new list is created upon load call)*/
			SaveLoad.GameTestData.Add (new DemographicData());
		}
	}

Hopes this helps someone in the future.