Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从一个保存文件反序列化多个不相关的ScriptableObject_C#_Unity3d_Scriptable Object - Fatal编程技术网

C# 从一个保存文件反序列化多个不相关的ScriptableObject

C# 从一个保存文件反序列化多个不相关的ScriptableObject,c#,unity3d,scriptable-object,C#,Unity3d,Scriptable Object,我想将多个不相关的ScriptableObjects对象保存到一个保存文件中。这样,我就可以保存/加载任何我想跟踪的数据。即:门未上锁、库存、高分、发现宝箱等。。这样,我仍然可以使用ScriptableObjects,保存和/或重新加载在DataManager控制下的任何内容。我希望DataManager除了保存和重新加载ScriptableObjects及其保存的数据外,什么都不做 在我看来,将不同的ScriptableObjects保存到一个文件似乎效果不错。如果我打开data\u edi

我想将多个不相关的
ScriptableObjects
对象保存到一个保存文件中。这样,我就可以保存/加载任何我想跟踪的数据。即:门未上锁、库存、高分、发现宝箱等。。这样,我仍然可以使用
ScriptableObjects
,保存和/或重新加载在
DataManager
控制下的任何内容。我希望
DataManager
除了保存和重新加载
ScriptableObjects
及其保存的数据外,什么都不做

在我看来,将不同的
ScriptableObjects
保存到一个文件似乎效果不错。如果我打开
data\u editor.sav
文件,我可以看到数据已经序列化并放入文件中

{"serializedObjects":["{\"GUID\":\"e27e7e59111210141bb70cbdff58f4f6\",\"Prefab\":{\"instanceID\":3648}}","{\"GUID\":\"52abd33f0dd972246b5eaa87a938331e\",\"Prefab\":{\"instanceID\":3190}}","{\"GUID\":\"78d783846b8abb3488ee1e274773aec6\",\"Prefab\":{\"instanceID\":3080}}"]}
但是,读回数据,并尝试重新填充我的
DataManager
managedData
属性是不断中断的。我一辈子都不知道如何将JSON字符串反序列化回
ScriptableObjects

我得到一个错误:

ArgumentException:无法将JSON反序列化为类型为的新实例 “ScriptableObject。”

我已经研究了几个SO问题,但似乎找不到任何关于将多个不同的
ScriptableObjects
管理为一个对象的方法

有什么帮助吗

我尝试了
JsonUtility.FromJsonOverwrite
JsonUtility.FromJson
的变体,但我无法让它工作

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

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

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();
        }
}
public interface IDataSaver {
        void Save(DataStore data);
        bool Load(DataStore data);
}
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来执行(反)序列化工作,最好使用自定义类和
SerializableAttribute
ScriptableObject
包含像GUID一样的无用数据

我尝试了JsonUtility.FromJsonOverwrite和 但是我无法让它工作

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

我不会写这篇文章作为答案,因为我不是100%确定,我现在没有时间去研究它,但我从过去的类似尝试中记得:SOs实际上只是一种资产,就像你项目中的一个图像文件。即使你关闭了游戏,它们仍然存在。当你序列化他们的数据时,你所做的就是这些;序列化他们的数据,但资产仍然存在。反序列化后,您不应尝试实例化SOs,而应使用反序列化后的数据重新填充现有SOs。希望有帮助。