ProAndrewGrammer
ProAndrewGrammer

Reputation: 23

Vector3 not serializable Unity3D

Ok so I followed the Unity3D data persistence tutorial, everything is going smoothly until I tried to save a Vector3 type of data. The tutorial only shows how to save int and strings.

When I used the function Save() , the consoles shows me that says: "SerializationException: Type UnityEngine.Vector3 is not marked as Serializable.

But as you can see from my code, I included it under the Serializable part. I am trying to save my playerPosition. Thanks

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

public class GameManager : MonoBehaviour 
{
    public static GameManager control;

public float health;
public float mana;
public float experience;
public Vector3 playerPosition;
public List<Item> inventory = new List<Item>();

void Awake()
{
    if(control == null)
    {
        DontDestroyOnLoad(gameObject);
        control = this;
    }
    else if(control != this)
    {
        Destroy(gameObject);
    }
}

// Use this for initialization
void Start (){}

// Update is called once per frame
void Update () {}

void OnGUI() 
{
    GUI.Box(new Rect(10, 10, 100, 30), "Health: " + health);
    GUI.Box(new Rect(10, 30, 100, 30), "Mana: " + mana);
    GUI.Box(new Rect(10, 50, 100, 30), "Experience: " + experience);
}

public void SaveSlot1()
{
    BinaryFormatter bf = new BinaryFormatter();
    FileStream file = File.Create(Application.persistentDataPath + 
                                  "/saveData1.dat");

    PlayerData data = new PlayerData();
    data.health = health;
    data.mana = mana;
    data.experience = experience;
    data.playerPosition = playerPosition;

    for(int i = 0; i <inventory.Count; i++)
    {
        //data.inventory[i] = inventory[i];
    }

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

public void LoadSlot1()
{
    if(File.Exists(Application.persistentDataPath +
                   "/saveData1.dat") )
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Open(Application.persistentDataPath + 
                                    "/saveData1.dat", FileMode.Open);
        PlayerData data = (PlayerData)bf.Deserialize(file);
        file.Close();

        health = data.health;
        mana = data.mana;
        experience = data.experience;
        playerPosition = data.playerPosition;

        for(int i = 0; i <inventory.Count; i++)
        {
            //inventory[i] = data.inventory[i];
        }
    }

}

[Serializable]
class PlayerData
{
    public float    health;
    public float    mana;
    public float    experience;
    public Vector3  playerPosition;
    public List<Item> inventory = new List<Item>();

    //position
    //spells
    //
}
}

Upvotes: 2

Views: 4686

Answers (1)

Steve Mitcham
Steve Mitcham

Reputation: 5313

Marking something as Serializable just let's .NET to know that you are going to be using serialization. At that point every property all the way down the data model must also be serializable, either by being inherently serializable like ints and strings, or being a type that is also marked as serializable. There's a couple of options

[Serializable]
class PlayerData
{
    public PlayerData()
    {
       playerPosition = Vector3.zero;
    }

    public float    health;
    public float    mana;
    public float    experience;
    [NonSerialized]
    public Vector3  playerPosition;

    public double playerPositionX
    { 
       get 
       {
         return playerPosition.x;
       }
       set
       {
         playerPosition.x = value;
       }
    }
    public double playerPositionY
    { 
       get 
       {
         return playerPosition.y;
       }
       set
       {
         playerPosition.y = value;
       }
    }

    public double playerPositionZ
    { 
       get 
       {
         return playerPosition.z;
       }
       set
       {
         playerPosition.z = value;
       }
    }

    public List<Item> inventory = new List<Item>();
}

This first option will not serialize the vector field, and instead use the properties. Having a vector to start with is important.

The other option is to implement the ISerializable interface on your class and then specifically control what fields are being written. The interface is somewhat tricky to implement, here is a MSDN link that explains some good and bad examples

Upvotes: 3

Related Questions