Saving a List of Classes that contain Ref and Value Types?
Posted: Tue Dec 31, 2019 6:30 pm
Hi! I've been integrating ES3 into my game and so far it's been perfect. I've had no trouble making save types of complex data structures-- but I am getting caught up on how to properly tell ES3 to save my game's Inventory.
My Game's inventory is a List of type "ItemInstance" that is a class that contains one ScriptableObject Reference, and one int. I'd like to be able to tell ES3 to save the entire list- but ES3 doesn't seem to understand how to properly save a List of classes when the class contains a mixture of Reference and Value type properties. Specifically, I'm looking for a way to get ES3 to properly save a List of type ItemInstance such that, on load, NEW ItemInstances are generated and the ItemIds are loaded by Reference, while the ItemCount is loaded by value.
Is this currently possible to do, or would I have to deserialize my ItemInstance and turn it into a struct to get ES3 to interpret it correctly? Thanks!
Code and more details about what I've attempted so far is below:
The Class that contains this is itself a Scriptable Object of type TL_Inventory. I've set up my TL_Inventory as an ES3Type. I have flagged _inventoryItems as a saved Property in ES3.
Finally, I implemented a Saved Inventory that wraps the TL_Inventory and handles the Save/Load interface between my game's API and EasySave's.
With the code above, this is the Save Data for the Inventory that ES3 outputs for an inventory Containing 1 Item with a stack count of 12:
The data seems to be saved properly (with ItemId getting an _ES3Ref, and ItemCount getting an int)- but I'm concerned about the preceding _ES3Refs. This saves and loads properly as long as I keep Unity running-- but when I load after a unity Reset, the Length of the List is correct, and the ItemCount is correct- but the ItemId becomes null. I think this is because ES3 is actually trying to save a Reference to the ItemInstance class instance-- which shouldn't be happening. (I want it to generate a new ItemInstance and populate it with the ItemId and ItemCount data.)
I've tried playing around with "ES3.ReferenceMode", but if I save by RefAndValue or by Value it ends up trying to do a deep copy of the content of the ItemId ScriptableObject (which I don't want, since that's the data that defines an item's parameters and doesn't need to be saved.)
Do you have any insight into how I can get ES3 to properly save/load a List of classes like this? Thanks again!
My Game's inventory is a List of type "ItemInstance" that is a class that contains one ScriptableObject Reference, and one int. I'd like to be able to tell ES3 to save the entire list- but ES3 doesn't seem to understand how to properly save a List of classes when the class contains a mixture of Reference and Value type properties. Specifically, I'm looking for a way to get ES3 to properly save a List of type ItemInstance such that, on load, NEW ItemInstances are generated and the ItemIds are loaded by Reference, while the ItemCount is loaded by value.
Is this currently possible to do, or would I have to deserialize my ItemInstance and turn it into a struct to get ES3 to interpret it correctly? Thanks!
Code and more details about what I've attempted so far is below:
Code: Select all
[System.Serializable]
public class ItemInstance
{
public TL_InventoryItem ItemId;
public int ItemCount;
public ItemInstance()
{
ItemId = null;
ItemCount = 0;
}
public ItemInstance(TL_InventoryItem newItemID, int newItemCount)
{
ItemId = newItemID;
ItemCount = newItemCount;
}
}
Code: Select all
public class TL_Inventory : ScriptableObject
{
[SerializeField]
private List<ItemInstance> _inventoryItems = new List<ItemInstance>();
public List<ItemInstance> InventoryItems { get { return _inventoryItems; } }
}
Code: Select all
public class SavedInventory : SavedObject<TL_Inventory>
{
public SavedInventory(TL_Inventory newObj) : base(newObj) { }
public override void SaveToFile(string fileName)
{
ES3Settings settings = new ES3Settings(true);
settings.memberReferenceMode = ES3.ReferenceMode.ByRef;
ES3.Save<TL_Inventory>(SerializedName, Var, fileName, settings);
}
public override bool LoadFromFile(string fileName)
{
if (ES3.KeyExists(SerializedName, fileName))
{
ES3.LoadInto(SerializedName, fileName, Var);
return true;
}
return false;
}
public override void ResetData()
{
Var.ClearInventory();
}
}
Code: Select all
{"Player Inventory":{"__type":"Tavernlight.Inventory.TL_Inventory,Assembly-CSharp","value":{"_ES3Ref":9118728620226211164,"_ES3Ref":9118728620226211164,"_inventoryItems":[{"ItemId":{"_ES3Ref":1000487261940427266},"ItemCount":12}]}}
I've tried playing around with "ES3.ReferenceMode", but if I save by RefAndValue or by Value it ends up trying to do a deep copy of the content of the ItemId ScriptableObject (which I don't want, since that's the data that defines an item's parameters and doesn't need to be saved.)
Do you have any insight into how I can get ES3 to properly save/load a List of classes like this? Thanks again!