doyh
doyh

Reputation: 21

<< SerializationException : Type 'UnityEngine.MonoBehaviour' ... is not marked as serializable >>?

I would like to save the data with a binary form but it doesn't work and says << SerializationException: Type 'UnityEngine.MonoBehaviour' in Assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable. >> Do you know what is the problem?

Here is some parts of my << DataManager >> Script :

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();
}

And here are some parts of << GameManager >> script :

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();
}

This is the GameData script :

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>();
    }
}

Upvotes: 2

Views: 3936

Answers (2)

derHugo
derHugo

Reputation: 90871

In general you should NOT use BinaryFormatter anymore at all!

Consider rather serializing via JSON or XML


Also in general don't use +"/..." for system paths. As different platforms use different system path separators you should rather use Path.Combine which always uses the correct separator depending on the platform (OS)

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

Finally don't directly (de)serialize a MonoBehaviour!

It makes no sense since a MonoBehaviour may not exist without being attached to a GameObject .. so you can't deserialize it (in a valid way) anyway and using new on it is forbidden .. which is what the BinaryFormatter internally does.

The only exception for this is stuff like JsonUtility.FromJsonOverwrite since it doesn't create a new instance but rather overwrites the fields of an already existing one.

Rather use a "normal" [Serializable] data contianer class. As soon as a script is

  • not directly related to a specific GameObject
  • doesn't need any MonoBehaviour messages like Update, Awake etc

It should not inherit from MonoBehaviour at all but rather simply store the data like e.g.

// 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
}

and in the manager have

public GameData gameData = new GameData();

Upvotes: 2

defaultUsernameN
defaultUsernameN

Reputation: 797

Your GameData class needs to have a [Serializable] attribute. Depending on what's in that class, you also might want to define how it is serialized.

This question might also help.

Upvotes: -1

Related Questions