Unity反序列化另一个项目中的对象

时间:2017-10-08 01:32:53

标签: class unity3d serialization deserialization loading

我正在创建一个工具,帮助我的工作室中的艺术家轻松设计他们的UI,然后让他们能够将UI导出到开发人员以在他们的项目中使用。

长话短说,我遵循了本教程:What is the best way to save game state?

当我在同一个脚本中编写所有内容时,它正常工作。

然而,当我打开另一个Unity项目来导入数据时,它停止了正常工作。它会读取文件,但是应该实例化的spawnObject变量保持为空。

我在这里使用的类名为UIdata,它只有一个gameobject变量是inputObject,而且该类与我从其他项目导出的类完全相同

我不太确定它为什么不起作用,如果从另一个项目导入某些东西,可以进行反序列化工作吗?

这是我的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Runtime.Serialization;
using System.Xml.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System;
public class DataSaver
{
    public static void saveData<T>(T dataToSave, string dataFileName)
    {
        string tempPath = Application.streamingAssetsPath + "/newUICorrect.txt";
        string jsonData = JsonUtility.ToJson(dataToSave, true);
        byte[] jsonByte = Encoding.ASCII.GetBytes(jsonData);

        if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
        {
            Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
        }

        try
        {
            File.WriteAllBytes(tempPath, jsonByte);
            Debug.Log("Saved Data to: " + tempPath.Replace("/", "\\"));
        }
        catch (Exception e)
        {
            Debug.LogWarning("Failed To PlayerInfo Data to: " + tempPath.Replace("/", "\\"));
            Debug.LogWarning("Error: " + e.Message);
        }
    }

    public static T loadData<T>(string dataFileName)
    {
        string tempPath = Application.streamingAssetsPath + "/newUICorrect.txt";
        if (!Directory.Exists(Path.GetDirectoryName(tempPath)))
        {
            Debug.LogWarning("Directory does not exist");
            return default(T);
        }

        if (!File.Exists(tempPath))
        {
            Debug.Log("File does not exist");
            return default(T);
        }
        else
        {
            Debug.Log("found file");
        }
        byte[] jsonByte = null;
        try
        {
            jsonByte = File.ReadAllBytes(tempPath);
            Debug.Log("Loaded Data from: " + tempPath.Replace("/", "\\"));
        }
        catch (Exception e)
        {
            Debug.LogWarning("Failed To Load Data from: " + tempPath.Replace("/", "\\"));
            Debug.LogWarning("Error: " + e.Message);
        }

        string jsonData = Encoding.ASCII.GetString(jsonByte);

        object resultValue = JsonUtility.FromJson<T>(jsonData);
        return (T)Convert.ChangeType(resultValue, typeof(T));
    }
}

[System.Serializable]
public class UIData
{
    public GameObject inputObject;
}

public class LoadingScript : MonoBehaviour
{
    private GameObject objectToSpawn;
    void Start()
    {

    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I))
        {
            importObject();
        }
    }
    public void importObject()
    {
        UIData loadedData = new UIData();
        loadedData = DataSaver.loadData<UIData>("UI");
        objectToSpawn = loadedData.inputObject;


        if (loadedData == null)
        {
            return;
        }
        print(objectToSpawn);
    }
}

1 个答案:

答案 0 :(得分:0)

@Programmer是正确的,you cannot serialize engine types。有几种方法可以解决您的问题。第一种是通过以下列方式(伪代码)序列化MonoBehaviour组件来重建游戏对象:

public GameObject TestSaveAndLoadComponent(MyMonoBehaviour myComponent, GameObject objectToLoadComponentOnto){
        // convert component to Json
        string jsonString = JsonUtility.ToJson(myComponent);

        // Pretend to save the json string to File
        string directory = "TestDirectory";
        string file = "objectFile";
        SaveLoadData.SaveString(directory,file,objectJson);

        // load string from file
        string loadString = SaveLoadData.LoadString(directory,file);

        // add a MonoBehaviour component to the object so that it can be
        // overwritten by the JsonUtility
        MyMonoBehaviour componentToOverwrite = objectToLoadComponentOnto.AddComponent<MyMonoBehaviour>();
        JsonUtility.FromJsonOverwrite(loadString, componentToOverwrite);

        return newObject;
}

JsonUtility可能无法提供您的monoBehaviour类的深层副本,我不会使用它太多。它非常简陋,如果不能满足您的需求,总会有Json.Net for unity

总而言之,如果使用模型 - 视图 - 控制器模式以正确的方式构造代码,则不需要序列化gameObjects或monobehaviours。在这种情况下,您只需要序列化为UI定义Model的非常简单的类,然后您的视图类将在给定模型的单独场景或项目中重建ui。