List being overwritten mysteriously

I have a simple class called Item, and a script called DatabaseManager which loads a list of items from a file and allows me to make changes and save them to the file. This works fine. The DatabaseManager uses an editor script (custom inspector). I have it set to create another list of Item when the database is loaded from the file, and this list (called “revert”) is never changed. This is so that if the “Discard Changes” button is pressed, it can display the original item values again by setting the actual list of Item in the DatabaseManager script to equal the revert list. This in theory should work, and the revert list is loaded correctly (when the database file is loaded both lists are identical). But somehow, if I make changes to an item and press the discard changes button, it does not debug that the revert list has been changed (I have it set to do this any time the list is altered, which should only be when it’s loaded), but when setting the values in the original list to the values of the revert list they somehow stay the same. This may seem confusing, but it’s not. I’ll attach the scripts and a screenshot of the console log so you can understand better. Note: I have a custom debugging class, so C.Write or C.Error etc is just a Debug.Log that uses colours and only debugs if a setting in another script is enabled. Nothing fancy.

If someone could please help me figure out why it appears to be changing the revert list without me telling it to I would be forever in your debt! If you provide any information then many thanks for taking your time to help me, I appreciate it.

The Manager Script

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class DatabaseManager : MonoBehaviour {

	public List<Item> items = new List<Item>();
}

The Item Class

[System.Serializable]
public class Item {
	public int ItemID;
	public string ItemName;
	public string ItemDescription;
	public bool ItemIsEmpty;
	public bool ItemIsSellable;
	public bool ItemIsBuyable;
	public float ItemSellPrice;
	public float ItemBuyPrice;

	public Item () { ItemIsEmpty = true; }
	public static Item current;
}

The Manager Editor Script (The long, tedious one)

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

[CustomEditor(typeof(DatabaseManager))]
public class DatabaseManagerEditor : Editor {

	static bool loadedDB = false, saved = false, discarded = false;
	static bool edit = false;
	static List<Item> revert = new List<Item>();

	public override void OnInspectorGUI()
	{
		DatabaseManager t = (DatabaseManager)target;

		if(!loadedDB){
			if(GUILayout.Button("Load Database")){
				C.Title("Database Manager");
				C.Write("Preparing to load the database");
				t.items.Clear();
				if(File.Exists(Application.persistentDataPath + "/itemDatabase.igf")) {
					BinaryFormatter bf = new BinaryFormatter();
					FileStream file = File.Open(Application.persistentDataPath + "/itemDatabase.igf", FileMode.Open);
					C.Warning("SETTING ITEMS LIST");
					t.items = (List<Item>)bf.Deserialize(file);
					file.Close();
					C.Write("Success! Loaded from " + Application.persistentDataPath + "/itemDatabase.igf");

					revert.Clear();
					C.Warning("SETTING REVERT LIST");
					revert = t.items;

					// Debug
					C.Title("All Database Items");
					for(int i = 0; i < t.items.Count - 1; i++){
						C.ItemInfo(t.items*);*
  •  			}*
    
  •  			C.Title("All revert list items");*
    
  •  			for(int i = 0; i < revert.Count - 1; i++){*
    

_ C.ItemInfo(revert*);_
_
}*_

* loadedDB = true;*
* saved = false;*
* discarded = true;*
* edit = false;*
* }*
* else {*
* C.Error(“DM001”, “Could not load the item database. File does not appear to exist”);*
* }*
* }*
* } else {*
* if(!saved && !discarded){*
* EditorGUILayout.HelpBox(“Editing Enabled!”, MessageType.Warning);*
* }*
* else {*
* EditorGUILayout.HelpBox(“Editing Disabled!”, MessageType.Warning);*
* }*

* for(int i = 0; i < t.items.Count - 1; i++){*
* EditorGUILayout.BeginHorizontal();*

* // SHOW ITEM INFORMATION*
* if(!edit){*
* // NON EDITABLE*
_ GUILayout.Label(t.items*.ItemName);
} else {
// EDITABLE*
t.items.ItemName = GUILayout.TextField(t.items*.ItemName);
}*_

* EditorGUILayout.EndHorizontal();*
* }*

* if(!saved && !discarded){*
* if(GUILayout.Button(“Discard Changes”)){*
* C.Title(“Revert Changes”);*
* C.Warning(“Reverting Changes”);*
* for(int i = 0; i < revert.Count - 1; i++){*
t.items = revert*;*
C.Write(“Setting ‘’” + t.items_.ItemName + “‘’ back to ‘’” + revert*.ItemName + “‘’”);
}*_

* discarded = true;*
* edit = false;*
* C.Write(“Changes discarded”);*
* }*

* if(GUILayout.Button(“Save Database”)){*
* if(EditorUtility.DisplayDialog(“Save Changes?”, “Are you sure you wish to overwrite the database?”, “Yes”, “No”)){*
* C.Title(“Database Manager”);*
* C.Write(“Preparing to save the database”);*
* DB.IDB.Add(Item.current);*
* BinaryFormatter bf = new BinaryFormatter();*
* FileStream file = File.Create (Application.persistentDataPath + “/itemDatabase.igf”);*
* bf.Serialize(file, t.items);*
* file.Close();*
* C.Write("Success! Saved to " + Application.persistentDataPath + “/itemDatabase.igf”);*
* saved = true;*
* edit = false;*
* } else {*
* C.Write(“Did not save”);*
* saved = false;*
* }*
* }*
* }*
* else {*
* if(GUILayout.Button(“Make Changes”)){*
* loadedDB = true;*
* saved = false;*
* discarded = false;*
* edit = true;*
* }*

* if(GUILayout.Button(“Unload Database”)){*
* C.Warning(“CLEARING ITEMS LIST”);*
* t.items = new List();*
* C.Warning(“CLEARING REVERT LIST”);*
* revert = new List();*
* loadedDB = false;*
* }*
* }*
* }*
* }*

}

Before making changes
[40794-sc1.png|40794]
After making changes and pressing discard
[40795-sc2.png*|40795]*
*
*

You’re not saving the state of the modified objects! Item is declared as a class, which is passed-by-reference. So you don’t make a copy of the object by assigning it to another variable. Instead, both variables will now reference the same object and changes made through the first variable will modify the object, and the changes can be observed when you access the object through the second variable.

This is especially occurring at line 85, where you just assign the same objects that you just modified back into the list. The objects are already modified and you never saved the internal state of the objects.

If you want that behavior, use a struct Item instead. It’s passed-by-value and will create copies each time it is reassigned (just like an integer would). Otherwise you’d have to create deep copies of your objects by newing an Item and copying over all fields.

Okay, I resolved this by simply changing the code to reload the database from the file again when the discard changes button was pressed. I got rid of the revert list altogether. This is a classic example of me not thinking clearly, but hopefully someone can find this useful.