我想将多个不相关的ScriptableObjects
对象保存到一个保存文件中。这样,我可以保存/加载任何我想跟踪的数据。 IE浏览器门未上锁,库存,高分,发现百宝箱等。通过这种方式,我仍然可以使用ScriptableObjects
,并将受DataManager
控制的任何内容保存和/或重新加载到某个点。我希望DataManager
除了保存并用其保存的数据重新加载ScriptableObjects
外,什么也不做。
在我看来,将不同的ScriptableObjects
保存到一个文件似乎可以正常工作。如果打开data_editor.sav
文件,则可以看到数据已被序列化并放入文件中。
{"serializedObjects":["{\"GUID\":\"e27e7e59111210141bb70cbdff58f4f6\",\"Prefab\":{\"instanceID\":3648}}","{\"GUID\":\"52abd33f0dd972246b5eaa87a938331e\",\"Prefab\":{\"instanceID\":3190}}","{\"GUID\":\"78d783846b8abb3488ee1e274773aec6\",\"Prefab\":{\"instanceID\":3080}}"]}
但是,不断读取数据并尝试重新填充我的DataManager
的{{1}}属性是一件令人沮丧的事情。我一辈子都想不通如何将JSON字符串反序列化为managedData
。
我得到了错误:
ArgumentException:无法将JSON反序列化为类型的新实例 “ ScriptableObject”。
我已经看过几个including this one这样的问题,但似乎找不到任何可以将多个ScriptableObjects
管理成一个的问题。
有帮助吗?
我尝试了ScriptableObjects
和JsonUtility.FromJsonOverwrite
的变体,但无法正常工作。
数据存储 这是写入磁盘的类。
JsonUtility.FromJson<ScriptableObject>
从保存文件中读取数据后,我可以输出以查看SO的数据。
SO的外观如下
DataManager
[Serializable]
public class DataStore : ISerializationCallbackReceiver
{
public List<string> serializedObjects;
public DataStore()
{
serializedObjects = new List<string>();
}
#region ISerializationCallbackReceiver_Methods
/// <summary>
/// Serialization implementation from ISerializationCallbackReceiver
/// </summary>
public void OnBeforeSerialize() {}
/// <summary>
/// Deserialization implementation from ISerializationCallbackReceiver
/// </summary>
public void OnAfterDeserialize()
{
Debug.Log("OnAfterDeserialize Loaded Count: " + serializedObjects.Count);
foreach (string so in serializedObjects)
{
Debug.Log(so);
}
}
#endregion
public void AddSerializedObjects(List<ScriptableObject> scriptableObjects)
{
foreach(ScriptableObject so in scriptableObjects)
{
serializedObjects.Add(JsonUtility.ToJson(so));
}
}
public List<ScriptableObject> GetStoredSerializedObjects()
{
//return JsonUtility.FromJsonOverwrite(serializedObjects.ToString(), new List<ScriptableObject>());
List<ScriptableObject> temp = new List<ScriptableObject>();
foreach (string so in serializedObjects)
{
//ScriptableObject file = ScriptableObject.CreateInstance(JsonUtility.FromJson<ScriptableObject>(so));
var json = JsonUtility.FromJson<ScriptableObject>(so);
//JsonUtility.FromJsonOverwrite(so, stemp);
ScriptableObject file = ScriptableObject.CreateInstance((ScriptableObject)json);
temp.Add(file);
}
return temp;
}
}
IDataSaver
public class DataManager : MonoBehaviour
{
public List<ScriptableObject> managedData = new List<ScriptableObject>();
private DataStore m_Data;
[NonSerialized]
private IDataSaver m_Saver;
private void Awake()
{
m_Saver = new JsonSaver();
m_Data = new DataStore();
LoadData();
}
public void SaveData()
{
m_Data.AddSerializedObjects(managedData);
m_Saver.Save(m_Data);
}
public void LoadData()
{
Debug.Log("LoadData()");
m_Saver.Load(m_Data);
//Here is where I am trying to put the scriptable objects back
//managedData.Clear();
//managedData.AddRange(m_Data.GetStoredSerializedObjects()));
//managedData = m_Data.GetStoredSerializedObjects();
}
}
JsonSaver
public interface IDataSaver {
void Save(DataStore data);
bool Load(DataStore data);
}
答案 0 :(得分:0)
在谈论这个问题之前,我建议如果您决定使用json来进行(反)序列化工作,则最好将自定义类与SerializableAttribte
配合使用,ScriptableObject
包含了简单的数据就像 GUID 。
我尝试了JsonUtility.FromJsonOverwrite和 JsonUtility.FromJson,但我无法正常工作。
它们都可以使用,问题是您不能将文本(json字符串)反序列化回ScriptableObject
对象,因为json序列化过程不包括类型信息,您需要记录它自己一个人。
示例写作
foreach(ScriptableObject so in scriptableObjects)
{
string name = so.GetType().Name;
serializedObjects.Add(name); // Record the type name
serializedObjects.Add(JsonUtility.ToJson(so));
}
阅读时
string name = serializedObjects[0]; // The recorded type name
string json = serializedObjects[1];
ScriptableObject so = ScriptableObject.CreateInstance(name);
JsonUtility.FromJsonOverwrite(json, so);