gpt4 book ai didi

c# - 从一个保存文件反序列化多个不相关的 ScriptableObjects

转载 作者:行者123 更新时间:2023-11-30 18:11:44 24 4
gpt4 key购买 nike

我想保存多个不相关的ScriptableObjects对象到一个保存文件。这样,我就可以保存/加载任何我可能想要跟踪的数据。 IE。开门、库存、高分、找到宝箱等。这样我仍然可以使用 ScriptableObjects ,并保存和/或重新加载到一个点任何受 DataManager 控制的东西.我想要 DataManager除了保存并重新加载 ScriptableObjects 什么也不做与他们保存的数据。

enter image description here

保存不同的ScriptableObjects在我看来,一个文件似乎工作正常。如果我打开 data_editor.sav文件,我可以看到数据已经序列化并放入文件中。

{"serializedObjects":["{\"GUID\":\"e27e7e59111210141bb70cbdff58f4f6\",\"Prefab\":{\"instanceID\":3648}}","{\"GUID\":\"52abd33f0dd972246b5eaa87a938331e\",\"Prefab\":{\"instanceID\":3190}}","{\"GUID\":\"78d783846b8abb3488ee1e274773aec6\",\"Prefab\":{\"instanceID\":3080}}"]}

但是,回读数据并尝试重新填充我的 DataManagermanagedData属性(property)是不断破裂的东西。我一辈子都想不出如何将 JSON 字符串反序列化回 ScriptableObjects .

我得到错误:

ArgumentException: Cannot deserialize JSON to new instances of type 'ScriptableObject.'

我看过几个 SO 问题,including this one ,但我似乎找不到任何涉及管理多个不同 ScriptableObjects 的内容合二为一。

有什么帮助吗?

我试过 JsonUtility.FromJsonOverwrite 的变体和 JsonUtility.FromJson<ScriptableObject>但我无法让它工作。

数据存储这是写入磁盘的类。

[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;
}
}

从保存文件中读回数据后,我可以输出以查看 SO 的数据。

enter image description here

这是 SO 的样子

enter image description here enter image description here

数据管理器

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();
}
}

IDataSaver

public interface IDataSaver {
void Save(DataStore data);
bool Load(DataStore data);
}

JsonSaver

public class JsonSaver : IDataSaver {

private static readonly string s_Filename = "data_editor.sav";
public static string GetSaveFilename()
{
return string.Format("{0}/{1}", Application.persistentDataPath, s_Filename);
}

protected virtual StreamWriter GetWriteStream() {
return new StreamWriter(new FileStream(GetSaveFilename(), FileMode.Create));
}

protected virtual StreamReader GetReadStream() {
return new StreamReader(new FileStream(GetSaveFilename(), FileMode.Open));
}

public void Save(DataStore data) {
string json = JsonUtility.ToJson(data);
using (StreamWriter writer = GetWriteStream()) {
writer.Write(json);
}
}

public bool Load(DataStore data) {
string loadFilename = GetSaveFilename();
if (File.Exists(loadFilename)) {
using (StreamReader reader = GetReadStream()) {
JsonUtility.FromJsonOverwrite(reader.ReadToEnd(), data);
}

return true;
}

return false;
}
}

最佳答案

在讨论这个问题之前,我建议如果你决定使用 json 来做(反)序列化工作,你最好使用带有 SerializableAttribte 的自定义类,ScriptableObject 包含您可以看到诸如 GUID 之类的多余数据。

I have tried variations on JsonUtility.FromJsonOverwrite and JsonUtility.FromJson but I couldn't get it to work.

它们都可以工作,问题是你不能将文本(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);

关于c# - 从一个保存文件反序列化多个不相关的 ScriptableObjects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56859245/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com