Saving/Loading ScriptableObject problem

Hello, first time poster long time lurker here.

I’ve been working on an editor tool for my game that allows the creation/modification of items. In my editor window script, when the user wants to save the current state of the item manager, I create an asset composed of the item manager (which derives from ScriptableObject) and save in the Resources folder for later use. However, if I try to make a change and re-save it, if I don’t call AssetDatabase.DeleteAsset() it tells me that the asset already exists. If I do call AssetDatabase.DeleteAsset(), then when I subsequently call AssetDatabase.CreateAsset() it tells me that the object is null. Also, upon trying to load the asset from file in the editor with AssetDatabase.GetAssetAtPath() or in game with Resources.Load(), the ItemManager variable comes up null.

Here’s some supplemental code that will hopefully help you understand what is going on.

void ExportItemList()
{
	GUILayout.Space(50.0f);
	if(GUILayout.Button("Export"))
	{
		string path = EditorUtility.SaveFilePanel("Export Items to Xml", ".", "items", "xml");
		XmlSerializer serializer = new XmlSerializer(typeof(List<Item>));
		TextWriter write = new StreamWriter(path);
		serializer.Serialize(write, itemmanager.Items);
		write.Close();

		AssetDatabase.DeleteAsset(@"Assets\Resources\ItemManager.asset");
                AssetDatabase.CreateAsset(itemmanager, @"Assets\Resources\ItemManager.asset");

		AssetDatabase.SaveAssets();

	}

}

	

void ImportItemList()
{
	GUILayout.Space(50.0f);
	if(GUILayout.Button("Import"))
	{
		string path = EditorUtility.OpenFilePanel("Import Item Manager", ".", "asset");

			itemmanager = (ItemManager)AssetDatabase.LoadAssetAtPath(path, typeof(ItemManager));

	}
}

Edit: Bad formatting. Well, it’s still pretty bad but I think that’s because I went past column 80 in code.

I suppose it’s probably a good idea to show you what ItemManager looks like.

[Serializable]
public class ItemManager : ScriptableObject
{	
	private List<Item> items;

	public List<Item> Items
	{
		get
		{
			return items;
		}
		set
		{
			items = value;
		}
	}

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

	public void AddItem(Item item)
	{
		items.Add(item);
	}

	public void RemoveItem(Item item)
	{
		items.Remove(item);
	}

	
	public Item GetItem(ulong id)
	{
		return items.Find(delegate(Item i) { return i.Id == id; });
	}

	public void SortById()
	{
		items.Sort(delegate(Item first, Item second) { if(first.Id > second.Id) return 1; else if(first.Id == second.Id) return 0; else return -1; });
	}

	public void SortByName()
	{
		items.Sort(delegate(Item first, Item second) { return String.Compare(first.Name, second.Name); });
	}
}

Thanks.

So after taking a break, and then coming back to it for a couple hours I realized that some of my classes were not marked [Serializable], and I should’ve been Saving/Loading the file like this:

//This is called when the Editor Window is created

itemmanager = (ItemManager)AssetDatabase.LoadAssetAtPath(@"Assets\Resources\ItemManager.asset", typeof(ItemManager));
if(itemmanager == null)
{
	AssetDatabase.CreateAsset(itemmanager, @"Assets\Resources\ItemManager.asset");
	itemmanager = (ItemManager)ScriptableObject.CreateInstance(typeof(ItemManager));
}

//And this is called when I want to save

if(!AssetDatabase.Contains(itemmanager))
       	AssetDatabase.CreateAsset(itemmanager, @"Assets\Resources\ItemManager.asset");
AssetDatabase.SaveAssets();

Also i found that your scriptableobject script must be defined in separated class,
Otherwise, when you use AssetDatabase.Create, it’s create asset well, but lost links to the script.

In last addiem7c5 code, swap line 8 with 7, otherwise null asset is passed.

Yes… to fix the “lost link to script” issue, you should make a separated cs file such as MyScriptableObject.cs that contains a class named MyScriptableObjec.

//in MyScriptableObject.cs
public class MyScriptableObject: ScriptableObject
{
    ... ...
}