尝试序列化int时出错

时间:2017-12-07 22:14:16

标签: c# unity3d serialization unity5 unityscript

我正在尝试序列化我的整数但是我收到以下错误:

  

InvalidCastException:无法从源类型转换为目标类型。

SaveLoad.Load()(在Assets / SaveLoad.cs:24处)引用另一个 只需在唤醒时加载它的脚本loadgame.Awake()(at Assets / loadgame.cs:8)指的是

StatContainer.totalcoins = (int)bf.Deserialize(file);

我是数据序列化的新手,有人可以解释我的错误在哪里吗?

using UnityEngine;
using System.Collections;
using System.Collections.Generic; 
using System.Runtime.Serialization.Formatters.Binary; 
using System.IO;

public static class SaveLoad {
//public static List<StatContainer> savedGames = new List<StatContainer>();

//it's static so we can call it from anywhere
public static void Save() {
    //SaveLoad.savedGames.Add(StatContainer.current);
    BinaryFormatter bf = new BinaryFormatter();
    //Application.persistentDataPath is a string, so if you wanted you can put that into debug.log if you want to know where save games are located
    FileStream file = File.Create (Application.persistentDataPath + "/savedGames.gd"); //you can call it anything you want
    bf.Serialize(file, StatContainer.current);
    file.Close();
}   

public static void Load() {
    if(File.Exists(Application.persistentDataPath + "/savedGames.gd")) {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Open(Application.persistentDataPath + "/savedGames.gd", FileMode.Open);
        StatContainer.totalcoins = (int)bf.Deserialize(file);
        file.Close();
        Debug.Log ("Loaded");
    }
}
}

2 个答案:

答案 0 :(得分:0)

调用Debug.Log(bf.Deserialize(file));查看它返回的对象类型,因为它显然不是int。

答案 1 :(得分:0)

好的,所以当你问三个关于同一问题的问题时,让我们完成这件事。 我将向您展示该过程的简化版本,因为您有太多数据。

[Serializable]
public class DataContainer
{
    public int dataA { get; private set; }
    public int dataB { get; private set; }
    public void SetValues(int a, int b){
        this.dataA = a; this.dataB = b;
    }
}

这是你的数据容器,没有静态值。成员是具有公共getter的属性,因此您可以从任何地方查看其值,但是setter是私有的,因此您必须使用该方法来修改它们。该方法可以有更多关于验证,例如,值是正值,还是小于屋顶值等等。

现在您需要实例化对象,以便可以访问数据。您可以在MonoBehaviour脚本中执行此操作:

public class DataController : MonoBehaviour
{
    private DataContainer data = null; // here is the reference
    void Start()
    {
           this.data = new DataContainer();  // Instantiate the object
           this.data.SetValues(10,20);
           Debug.Log(this.data.dataA + " " this.data.dataB);
    }
}

好吧,到目前为止,这么好,让我们进行序列化和保存。

public static class Save
{
    public static void SaveData<T>(object obj, string key) where T : class
    {
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();
        bf.Serialize(ms, items as T);
        PlayerPrefs.SetString(key, Convert.ToBase64String(ms.GetBuffer()));
    }
     public static T GetData<T>(string key) where T: class
    {
        string str = PlayerPrefs.GetString(key, null);
        if (string.IsNullOrEmpty(str) == true) { return null; }
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream(Convert.FromBase64String(str));
        return bf.Deserialize(ms) as T;
    }
}

这将存储在PlayerPrefs中,它使用泛型,因此您可以传递任何类型并重用任何项目的代码。有一个约束,所以你可以返回null。这意味着您只能传递类的类型并且不能传递struct。其余的已经知道了。只需关注转换(如T),这就是编译器理解预期类型的​​原因。

以下是您使用它的方式:

public class DataController : MonoBehaviour
{
    private DataContainer data = null; // here is the reference
    void Start()
    {
           this.data = new DataContainer();  // Instantiate the object
           this.data.SetValues(10,20);
           Debug.Log("Data : " + this.data.dataA + " " this.data.dataB);
           Save.SaveData<DataContainer>(this.data, "data");
           // At that point it is saved on disk
           // Let's get it back
           DataContainer newData = Save.GetData<DataContainer>("data");
           Debug.Log("New data : " + newData .dataA + " " newData.dataB);
    }
}