【问题标题】:<< SerializationException : Type 'UnityEngine.MonoBehaviour' ... is not marked as serializable >>?<< SerializationException : Type 'UnityEngine.MonoBehaviour' ...未标记为可序列化>>?
【发布时间】:2021-04-04 12:34:38
【问题描述】:

我想用二进制形式保存数据,但它不起作用并显示 > 你知道是什么问题吗?

这是我的 > 脚本的一些部分:

public class DataManager : MonoBehaviour {
private string dataPath;

public void Initialize() {
    dataPath = Application.persistentDataPath + "/gameData.dat";
}

public void Save(GameData gameData) {
    BinaryFormatter bf = new BinaryFormatter();
    FileStream file = File.Create(dataPath);

    GameData data = new GameData();
    data.level = gameData.level;
    data.hp = gameData.hp;
    data.mp = gameData.mp;
    data.damage = gameData.damage;
    data.exp = gameData.exp;
    data.maxExp = gameData.maxExp;
    data.equipItem = gameData.equipItem;

    bf.Serialize(file, data);
    file.Close();
}

下面是 > 脚本的一些部分:

public class GameManager : MonoBehaviour {
private static GameManager m_instance;
public static GameManager instance {
    get {
        if (m_instance == null) {
            m_instance = FindObjectOfType<GameManager>();
        }
        return m_instance;
    }
}

private DataManager dataManager;
public GameData gameData;

public event Action levelUp;
public bool isPlayerDead { get; private set; }


public void Awake() {
    if (instance != this) {
        Destroy(gameObject);
    }

    dataManager = GetComponent<DataManager>();
    dataManager.Initialize();

    LoadGameData();

    levelUp += UpdateMaxExp;
    levelUp += UpdateMaxHp;
    levelUp += UpdateMaxMp;
    levelUp += UpdateLevel;

    FindObjectOfType<PlayerHealth>().onDeath += PlayerDeath;
}

public void SaveGameData() {
    dataManager.Save(gameData);
}

public void OnApplicationQuit() {
    SaveGameData();
}

这是 GameData 脚本:

namespace DataInfo {
    [System.Serializable]
    public class GameData {
        public int level = 1;
        public float hp = 100f;
        public float maxHp = 100f;
        public float mp = 100f;
        public float maxMp = 100f;
        public float damage = 25f;
        public float exp = 0f;
        public float maxExp = 100;
        public List<Item> equipItem = new List<Item>();
    }
}

【问题讨论】:

  • 你能展示一下GameData的实现吗?
  • @derHugo 是的,我添加了它。

标签: c# unity3d serialization save


【解决方案1】:

一般您根本不应该再使用BinaryFormatter

考虑通过JSONXML 进行序列化


通常也不要将+"/..." 用于系统路径。由于不同的平台使用不同的系统路径分隔符,您应该使用 Path.Combine,它始终根据平台 (OS) 使用正确的分隔符

dataPath = Path.Combine(Application.persistentDataPath, "gameData.dat");

最后不要直接(反)序列化MonoBehaviour

这是没有意义的,因为 MonoBehaviour 可能不存在而不附加到 GameObject .. 所以你无论如何都不能反序列化它(以有效的方式)并且禁止在其上使用 new ..这就是 BinaryFormatter 在内部所做的。

唯一的例外是JsonUtility.FromJsonOverwrite 之类的东西,因为它不会创建新实例,而是覆盖现有实例的字段。

宁可使用“普通”[Serializable] 数据容器类。只要脚本是

  • 与特定游戏对象没有直接关系
  • 不需要任何MonoBehaviour 消息,例如UpdateAwake

它根本不应该从MonoBehaviour 继承,而是简单地存储数据,例如

// not a MonoBehaviour since it has no own behavior anyway
// So this doesn't need to be attached to a specific GameObject but rather simply exists
// somewhere in a field or property
[Serializable]
public class GameData
{
    // Your fields here
}

在经理有

public GameData gameData = new GameData();

【讨论】:

  • 哦,哈哈,我正在研究一本书,并且有一个二进制格式化程序部分。好吧我不会用。谢谢你的回答。但是 GameData 不是从 MonoBehaviour 继承的,我序列化了一个 GameData 类型的数据。那又是哪一部分的问题?
  • Item 是什么?那是MonoBehaviour 吗?
  • 否 也是DataInfo中可序列化的类
【解决方案2】:

您的GameData 类需要有一个[Serializable] attribute。根据该类中的内容,您可能还需要定义它的序列化方式。

This 问题也可能有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-15
    • 2017-02-21
    • 2015-11-10
    • 2016-01-18
    • 2011-01-17
    • 1970-01-01
    相关资源
    最近更新 更多