So according to Unity - Manual: Script serialization , I should be able to serialize Color and Vector2 Variables, but trying to do so gives the following error:
System.Runtime.Serialization.SerializationException: Type 'UnityEngine.Color' in Assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
I tested, and serializing it by simply deconstructing the Variables into Red, Green and Blue Float values for example, works fine, but I’m just wondering if anyone knows why this isn’t working, since it would be cleaner to just store the values directly instead of dismantling and putting them back together when saving and loading.
Here’s some of the lines interacting with the Serializeable “GameInfo” Class:
public void SaveData()
{
FileStream file = null;
try
{
BinaryFormatter bf = new BinaryFormatter();
file = File.Create(Application.persistentDataPath + path);
data = new GameInfo(
// The other Variables are being put here, just snipped out
GameObject.FindGameObjectWithTag("PlayerHat").GetComponent<SpriteRenderer>().color)
bf.Serialize(file, data);
}
catch (Exception e)
{
if (e != null)
{
Debug.Log(e);
}
}
finally
{
if (file!= null)
{
file.Close();
}
}
}
public void LoadData()
{
FileStream file = null;
try
{
BinaryFormatter bf = new BinaryFormatter();
file = File.Open(Application.persistentDataPath + path,FileMode.Open);
data = bf.Deserialize(file) as GameInfo;
// The other Variables are being put here, just snipped out
GameObject.FindGameObjectWithTag("PlayerHat").GetComponent<SpriteRenderer>().color = data.HatColor;
}
catch(Exception e)
{
if (e != null)
{
Debug.Log(e);
}
}
finally
{
if (file != null)
{
file.Close();
}
}
}
Heres the GameInfo Segment dealing with the HatColor (The Part I’m Testing with)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[Serializable]
public class GameInfo
{
private Color _HatColor;
public GameInfo() { }
public GameInfo(
Color HatColor
{
_HatColor = HatColor;
}
public Color HatColor
{
get
{
return _HatColor;
}
set
{
_HatColor = value;
}
}
}
I have had issues with Serialization and the solution I came up with is to convert the type into a serialazable class.
Example for your Hatcolor / any Color.
[Serializable]public class HatColor
{
public float _r;
public float _g;
public float _b;
public float _a;
public Color Color
{
get{
return new Color(_r, _g, _b, _a);
}
set{
_r = value.r;
_g = value.g;
_b = value.b;
_a = value.a;
}
}
}
This can be used when you have issues with any Unity object type that wont serialize.
You could further it to add methods to initialize it with the values for a color or a color itself but i will leave that to you.
EDIT: Added an example simple Serializable Color Class
using UnityEngine;
[System.Serializable]public class SerializableColor
{
public float _r;
public float _g;
public float _b;
public float _a;
public Color Color
{
get
{
return new Color(_r, _g, _b, _a);
}
set
{
_r = value.r;
_g = value.g;
_b = value.b;
_a = value.a;
}
}
public SerializableColor()
{
// (Optional) Default to white with an empty initialisation
_r = 1f;
_g = 1f;
_b = 1f;
_a = 1f;
}
public SerializableColor(float r, float g, float b, float a = 0f)
{
_r = r;
_g = g;
_b = b;
_a = a;
}
public SerializableColor(Color color)
{
_r = color.r;
_g = color.g;
_b = color.b;
_a = color.a;
}
}
Usages
SerializableColor = new SerializableColor(0f, 0f, 0f); // with Color Values
SerializableColor = new SerializableColor(Color.white); // With a Color
SerializableColor = new SerializableColor(); // Default to White
renderer.material.color = SerializableColor.Color;
You can use one simple class for the most part of Unity structs, use impliciti operators for easy conversion between Unity types and serialized type. Something like this:
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
public class Ser : MonoBehaviour
{
[ContextMenu("Test Serialize")]
void TestSerialize()
{
BinaryFormatter bf = new BinaryFormatter();
Vector2 vector2 = new Vector2(1, 4);
SerializableVector4 s_vector2 = vector2;
FileStream file = File.Open(Path.Combine(Application.persistentDataPath, "serialization_test_vector2.dat"), FileMode.OpenOrCreate);
bf.Serialize(file, s_vector2);
SerializableVector4 s_quaternion = transform.rotation;
file = File.Open(Path.Combine(Application.persistentDataPath, "serialization_test_quaternion.dat"), FileMode.OpenOrCreate);
bf.Serialize(file, s_quaternion);
SerializableVector4 s_color = Color.magenta;
file = File.Open(Path.Combine(Application.persistentDataPath, "serialization_test_color.dat"), FileMode.OpenOrCreate);
bf.Serialize(file, s_color);
file.Close();
Debug.Log("Serialized");
}
[ContextMenu("Test Deserialize")]
void TestDeserialize()
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Path.Combine(Application.persistentDataPath, "serialization_test_vector2.dat"), FileMode.Open);
Vector2 d_vector2 = (SerializableVector4)bf.Deserialize(file);
file.Close();
Debug.Log(d_vector2);
file = File.Open(Path.Combine(Application.persistentDataPath, "serialization_test_quaternion.dat"), FileMode.Open);
Quaternion d_quaternion = (SerializableVector4)bf.Deserialize(file);
file.Close();
Debug.Log(d_quaternion);
file = File.Open(Path.Combine(Application.persistentDataPath, "serialization_test_color.dat"), FileMode.Open);
Color d_color = (SerializableVector4)bf.Deserialize(file);
file.Close();
Debug.Log(d_color);
}
}
[System.Serializable]
public class SerializableVector4
{
public float a;
public float b;
public float c;
public float d;
// Quaternion
public static implicit operator Quaternion(SerializableVector4 sv)
{
return new Quaternion(sv.a, sv.b, sv.c, sv.d);
}
public static implicit operator SerializableVector4(Quaternion q)
{
return new SerializableVector4()
{
a = q.x,
b = q.y,
c = q.z,
d = q.w
};
}
// Color
public static implicit operator Color(SerializableVector4 sv)
{
return new Color(sv.a, sv.b, sv.c, sv.d);
}
public static implicit operator SerializableVector4(Color c)
{
return new SerializableVector4()
{
a = c.r,
b = c.g,
c = c.b,
d = c.a
};
}
// Vector2
public static implicit operator Vector2(SerializableVector4 sv)
{
return new Vector2(sv.a, sv.b);
}
public static implicit operator SerializableVector4(Vector2 v)
{
return new SerializableVector4()
{
a = v.x,
b = v.y
};
}
}