Save and Load System error

I’m attempting to implement a save and load system in my project but I keep on running into the following error whenever I press the save button:

NullReferenceException: Object reference not set to an instance of an object
System.Collections.Generic.Dictionary2[TKey,TValue].get_Keys () (at <9aad1b3a47484d63ba2b3985692d80e9>:0) System.Reflection.RuntimePropertyInfo.GetterAdapterFrame[T,R] (System.Reflection.RuntimePropertyInfo+Getter2[T,R] getter, System.Object obj) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[ ] index) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.RuntimePropertyInfo.GetValue (System.Object obj, System.Object[ ] index) (at <9aad1b3a47484d63ba2b3985692d80e9>:0)
SaveLoadUtility.WriteToDictionary (System.Type fieldType, System.String fieldName, System.Object fieldValue, System.Collections.Generic.Dictionary2[System.String,System.Object]& baseDict, System.Boolean isField) (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadUtility.cs:924) SaveLoadUtility.GetValues (System.Object baseInstance, System.Collections.Generic.Dictionary2[System.String,System.Object]& baseDict, System.Boolean checkForPropertySelector) (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadUtility.cs:676)
SaveLoadUtility.GetValues (System.Object baseInstance, System.Collections.Generic.Dictionary2[System.String,System.Object]& baseDict) (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadUtility.cs:570) SaveLoadUtility.WriteToDictionary (System.Type fieldType, System.String fieldName, System.Object fieldValue, System.Collections.Generic.Dictionary2[System.String,System.Object]& baseDict, System.Boolean isField) (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadUtility.cs:966)
SaveLoadUtility.GetValues (System.Object baseInstance, System.Collections.Generic.Dictionary`2[System.String,System.Object]& baseDict, System.Boolean checkForPropertySelector) (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadUtility.cs:676)
SaveLoadUtility.PackComponent (System.Object component) (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadUtility.cs:564)
SaveLoadUtility.PackGameObject (UnityEngine.GameObject go, ObjectIdentifier oi) (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadUtility.cs:522)
SaveLoadUtility.SaveGame (System.String saveGameName) (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadUtility.cs:207)
SaveLoadMenu.OnGUI () (at Assets/Dead Earth/Scripts/Unity Save Load Utility/SaveLoadMenu.cs:197)

When I double click on the error in the editor I’m redirected to the following lines of code in the “SaveLoadUtility.cs” script:

//Go through the OIsToSerialize array again to pack the GameObjects into serializable form, and add the packed data to the sceneObjects list of the new SaveGame instance.
if(true) {
foreach (ObjectIdentifier oi in OIsToSerialize) {
//Convert the GameObject's data into a form that can be serialized (an instance of SceneObject),
//and add it to the SaveGame instance's list of SceneObjects.
newSaveGame.sceneObjects.Add(PackGameObject(oi.gameObject, oi));
}
}

I’m using this asset I discovered called “USLU” (linked below) which is meant to be straightforward yet I still can’t wrap my head around this error.

I’m going to attach some files that relate to this error in particular. There are a few requirements for the save system to work (which I’ve fulfilled), first is that the “ObjectIdentifier.cs” script must be attached to the prefabs that I wish to save and second is that those prefabs must be placed in the “Assets/Resouces/prefabs” folder created after importing the asset.
Lastly, I have written “GameSaveManager.cs” script which fetches the player’s data, like health and inventory, and encrypts/decrypts it on save/load. I will also attach this file, tho I don’t think this script is causing any issues.

9025639–1245295–ObjectIdentifier.cs (2.91 KB)
9025639–1245298–SaveLoad.cs (7.46 KB)
9025639–1245301–SaveLoadMenu.cs (5.82 KB)
9025639–1245304–SaveLoadUtility.cs (56.9 KB)
9025639–1245307–GameSaveManager.cs (16 KB)

It doesn’t matter what you are doing because the answer is ALWAYS the same.

How to fix a NullReferenceException error

https://forum.unity.com/threads/how-to-fix-a-nullreferenceexception-error.1230297/

Three steps to success:

  • Identify what is null ← any other action taken before this step is WASTED TIME
  • Identify why it is null
  • Fix that
1 Like

Also, if you look at the thread, the developer for that asset says they no longer support it. I’m not sure when they stopped supporting it, but they made a lot of good comments on why they stopped supporting it. I suggest you look into other options for saving. It may be better to find a solution that still has support if you are unable to write your own solution.

1 Like

Simplify project data. Use JsonUtility for dynamic data (like game progress, list of items characters have) and ScriptableObjects for static data (list of all items in-game or power ups). About null exceptions already written above @Kurt-Dekker .

^ ^ ^ ^ ^ This. Everybody wants to “save all the state” of a running scene, as if it was a thing you can just rip out and do. Unity doesn’t even do that when they save the scene.

Save the absolute MINIMUM amount of data you can get away with. Any more save data instantly becomes a source of bugs.

As much as we groused with early console memory cards and even before that with on-cart flash ram, it kept you really honest and encouraged parsimony.

Load/Save steps:

https://discussions.unity.com/t/799896/4

An excellent discussion of loading/saving in Unity3D by Xarbrough:

https://discussions.unity.com/t/870022/6

Loading/Saving ScriptableObjects by a proxy identifier such as name:

https://discussions.unity.com/t/892140/8

When loading, you can never re-create a MonoBehaviour or ScriptableObject instance directly from JSON. The reason is they are hybrid C# and native engine objects, and when the JSON package calls new to make one, it cannot make the native engine portion of the object.

Instead you must first create the MonoBehaviour using AddComponent() on a GameObject instance, or use ScriptableObject.CreateInstance() to make your SO, then use the appropriate JSON “populate object” call to fill in its public fields.

If you want to use PlayerPrefs to save your game, it’s always better to use a JSON-based wrapper such as this one I forked from a fellow named Brett M Johnson on github:

https://gist.github.com/kurtdekker/7db0500da01c3eb2a7ac8040198ce7f6

Do not use the binary formatter/serializer: it is insecure, it cannot be made secure, and it makes debugging very difficult, plus it actually will NOT prevent people from modifying your save data on their computers.

https://docs.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide