【问题标题】:String is null after binary serialization二进制序列化后字符串为空
【发布时间】:2015-09-20 18:31:20
【问题描述】:

我正在制作一个简单的游戏,其中一个功能是将从文件中打开的挑战,这是其中一个挑战的外观:

[System.Serializable]
public class Challenge10 : ChallegeInterface {
    public bool isCompleted = false;
    public string description = "test";
    public int curCoins;
    public override void giveReward (){
        GameDataSingleton.gameDataInstance.game_data.addCoinsFromReward (7);
    }
    //Method to check if everything is completed
    public override bool isComplete (){ 
        if (!isCompleted) {
            curCoins= GameDataSingleton.gameDataInstance.game_data.getCoinsThisGame ();
            if (curCoins >= 1) {
                isCompleted = true;
                giveReward ();
                return true;
            }
        }
        return false;
    }
}

问题是在我反序列化文件后,字符串值(描述)为空。这是程序打开挑战的代码。

public void openChallenges(){
        challenges = new ChallegeInterface[game_data.challenges.Length];
        for (int i = 0; i < game_data.challenges.Length; i++) {
            int curChallenge = game_data.challenges[i];
            ChallegeInterface challenge = HddManager.HddManagerInstance.load<ChallegeInterface> ("challenges/challenge"+curChallenge);
            Debug.Log (challenge.description);
            challenges[i] = challenge;
        }
    }

除了描述之外,其他一切似乎都很好。我错过了什么吗?

编辑: 这是程序序列化对象的方式:

public void save<T>(T data, string fileName) where T : class{
        if (fileName == "")
            Debug.Log ("Empty file path");
        FileStream file = null;
        try{
            if(fileName.IndexOf("/") > 0){
                string[] strDirName = fileName.Split(new char[]  {'/'});
                string dirName = strDirName[0];
                if(!Directory.Exists(Path.Combine(Application.persistentDataPath, dirName))){
                    Directory.CreateDirectory(Path.Combine(Application.persistentDataPath, dirName));
                }
            }
            file = File.Create(Path.Combine(Application.persistentDataPath, fileName));
            binFormatter.Serialize(file, data);
            Debug.Log ("File saved succesfully" + fileName);
        }catch(IOException e){
            Debug.Log(e.ToString());
        }finally{
            if(file != null)
                file.Close();
        }
    }

这是反序列化对象的方式:

public T load<T> (string fileName) where T : class{ // T => object type
        if (fileName == null) {
            Debug.Log ("Empty path to file");
            return null;
        } else {
            FileStream file = null;
            try {
                //Open the file;
                file = File.Open (constructFilePath(fileName), FileMode.Open);
                //To be removed
                Debug.Log ("File loaded succesfully");
                // Deserialize the opened file, cast it to T and return it
                return binFormatter.Deserialize (file) as T;
            } catch (IOException e) {
                //To be removed
                Debug.Log (e.ToString ());
                // Saves the current object in case the file doesn't exist
                // Use Activator to create instance of the object,
                save (Activator.CreateInstance<T> (), fileName);
                // calls the function again
                return load<T> (fileName);
            } finally {
                //Close the file
                if (file != null)
                    file.Close ();
            }
        }
    }

【问题讨论】:

  • 你是如何序列化/去消毒你的对象的?改用xml序列化试试?
  • 我编辑了这个问题。作为最后的手段,我将重写一切以使用 XML,但如果可以修复此代码,那就太好了。
  • 奇怪,它对我来说很好,尝试在ChallegeInterface challenge = HddManager.HddManagerInstance.load&lt;ChallegeInterface&gt; ("challenges/challenge"+curChallenge); 行之后调试并手动检查描述。还是空的吗?
  • 我认为问题可能在于您正在尝试序列化接口。这里有更多info
  • 等等,你是怎么做到的?:ChallegeInterface challenge = HddManager.HddManagerInstance.load&lt;ChallegeInterface&gt; ("challenges/challenge"+curChallenge); Debug.Log (challenge.description); 接口不能包含字段。是一门课吗?如果是这样,您正在检查 Debug.Log(challenge.description) 中为空的基类字段...

标签: c# unity3d


【解决方案1】:

通过检查 openChallenges() 方法中的以下行:

ChallegeInterface challenge = HddManager.HddManagerInstance.load<ChallegeInterface> ("challenges/challenge"+curChallenge);
Debug.Log (challenge.description);

我假设ChallegeInterface 实际上是一个 而不是 接口 因为接口 不能包含 字段,并且您在访问challenge.descriptionchallengeChallegeInterface,这意味着 ChallengeInterface 是一个类。

在这种情况下,您实际上是在访问基类的 (ChallegeInterface) 字段,而不是正确的 (Challenge10)。并且该字段为空。

重要提示:保持清晰和正确的编码约定,永远不要命名一个类接口,最好避免用编程术语命名类型而不是与其用法相关的指示性命名。

P.S.:我自己检查了序列化并检查了 Challenge10 的描述,它工作正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-18
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    相关资源
    最近更新 更多