- Home /
Cannot serialize Color.
Hello, just to make things clear, Color is now serializable in Unity 4.5.
Issuing Debug.Log(System.Attribute.IsDefined(typeof(Color), typeof(System.SerializableAttribute))); returns true, Yay!
I've successfully done it with a simple test, but for some reason it isn't working in my real-case scenario. Here is a code excerpt. The error I am getting is Type UnityEngine.Color is not marked as Serializable. But it should work... I think the problem is in my functions, or the constructor. I am new to serialising data in Unity, so the problem is probably me :)
[System.Serializable]
public class Stats {
public int id;
public bool parentIsHead = false;
public float[] floatStats;// agility, thrust, thrustMag, thrustMagFreq, armour, hp;
public Color mainColor;// colorMain, colorSecondary;
public Color secondColor;
public Stats()
{
floatStats = new float[6];
mainColor = new Color(1,1,1);
secondColor = new Color(0,0,0);
Debug.Log(System.Attribute.IsDefined(typeof(Color), typeof(System.SerializableAttribute)));
}
public void initEmpty()
{
for (int i = 0; i < floatStats.Length; ++i)
floatStats[i] = 1;
// mainColor = new Color(0,0,0);
// secondColor = new Color(0,0,0);
}
public void initRandom()
{
for (int i = 0; i < floatStats.Length; ++i)
floatStats[i] = myRandom();
// TODO: Nice random colors
// mainColor = new Color(myRandomColor(), myRandomColor(), myRandomColor());
// secondColor = new Color(myRandomColor(), myRandomColor(), myRandomColor());
}
float myRandom()
{
return Random.Range(5, 10);
}
float myRandomColor()
{
// We don't want values close to .5, cause its ugly!
return Random.Range(0.0f, 1.0f);
}
}
Thanks in advance for any help!
Do you talk about .NET / $$anonymous$$ono's built-in serialization (things like XmlSerializer, ...) or do you talk about Unity's built-in custom serialization system? Where and how do you use this "Stats" class? Some more information would be helpful i guess.
I am talking about .Net serialization. This class is where I store everything about an object. It is used as such.
Answer by Socapex · Aug 19, 2014 at 02:13 AM
OK well it seems unsupported in a way. I ended rewriting everything 4 times, but now I love my current system. I use the usual binaryFormatter with a public data class (non monobehavior). But I have made my setters & getters reference this class even when the structs aren't serializable, so it automatically updates the data. Haven't seen anything like it in tutorials so here is a small example:
public class Piece : MonoBehaviour {
public Stats myStats;
public Color mainColor;
public Color secondColor;
public Color MainColor {
get { return mainColor; }
set { mainColor = value;
for(int i = 0; i < 4; ++i)
MyStats.mainColorArr[i] = mainColor[i]; }
}
public Color SecondColor {
get { return secondColor; }
set { secondColor = value;
for(int i = 0; i < 4; ++i)
MyStats.secondColorArr[i] = secondColor[i]; }
}
}
[System.Serializable]
public class Stats {
public float[] mainColorArr;
public float[] secondColorArr;
public Stats()
{
mainColorArr = new float[4];
secondColorArr = new float[4];
}
}
No need to copy everything at saving time, and all the data is always in sync :D Of course its weird to have getters/setters for public variables, but I need it for debugging in editor.
Answer by Marrt · Oct 12, 2017 at 05:32 PM
Why not use properties? and an implicit cast operator, now you can use SerializableColor just like you use Color:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class SerializableColor{
public float[] colorStore = new float[4]{1F,1F,1F,1F};
public Color Color{
get{ return new Color( colorStore[0], colorStore[1], colorStore[2], colorStore[3] );}
set{ colorStore = new float[4]{ value.r, value.g, value.b, value.a }; }
}
//makes this class usable as Color, Color normalColor = mySerializableColor;
public static implicit operator Color ( SerializableColor instance ){
return instance.Color;
}
//makes this class assignable by Color, SerializableColor myColor = Color.white;
public static implicit operator SerializableColor ( Color color ){
return new SerializableColor{ Color = color};
}
}
i hate the code formatter of this site...
This is genius and helped me 2 years later. I didn't know implicit casting was a thing til now, thanks!
Answer by Cherno · Aug 17, 2014 at 01:54 AM
Hmmm, maybe you need to use SerializeField, or if it doesn'T work anyway, just store the rgba values as seperate floats ;)
Well I kinda wanted to save everything in one pass... Wishfull thinking I guess ;)
Answer by Voxel-Busters · Jul 01, 2015 at 03:52 PM
You won't be able to serialise Vectors, Colors and Quaternions directly as they are not Serializable classes. But c# allows you to implement serialization extensions classes using ISerializationSurrogate. Check this link for more info https://msdn.microsoft.com/en-us/library/system.runtime.serialization.surrogateselector%28v=vs.110%29.aspx
But if you want to avoid all the trouble and save time, then check out Runtime Serialization for Unity fast and efficient plugin designed to handle serialization of c# class object as well Unity Objects like GameObject, Transform, Textures etc.
Looks like we're competitors @VoxelBusters. Sorry, I probably wouldn't have written this solution had yours come out slightly earlier. (You released after GameObject Serializer Pro started development). Btw, I solved the "unique GameObject name" problem you are having. You are more than welcome to check out how and apply a fix to your solution (assu$$anonymous$$g our methods are similar enough that the solution would apply)
@$$anonymous$$idnightStudiosInc appreciate your gesture :) We have already solved that "unique gameobject name" issue and it is scheduled for next update, which will be rolled out in a day or two.
Answer by antiart · Nov 28, 2015 at 03:10 AM
Is it really supported since 4.5? Because I still get an error with 5.2. Anyhow, I made a similar workaround inspired by Socapex:
[Serializable]
public class myClass {
[SerializeField]
float[] _myColor = new float[4]; // it's private
public Color MyColor {
get {
return new Color(_myColor[0], _myColor[1], _myColor[2], _myColor[3]);
}
set {
_myColor[0] = value.r;
_myColor[1] = value.g;
_myColor[2] = value.b;
_myColor[3] = value.a;
}
}
...
}
I'm a beginner and not sure if this is better. It seems a bit more simple, but then again only works for one color at a time... So far it seems to work fine :)
Haven't had to serialize colors in a while, but maybe your error is something else? From the doc.
Serializable types are:
Some built-in types like Vector2, Vector3, Vector4, Quaternion, $$anonymous$$atrix4x4, Color, Rect, Layer$$anonymous$$ask.
And also, I found this
[System.Serializable]
class Test : System.Object
{
public int p = 5;
public Color c = Color.white;
}
http://docs.unity3d.com/ScriptReference/Serializable.html
Good luck!
How odd :) I'm using the BitStream serialize and got the very same error you had in the original post. In the API-Docs Color is not listed for Bitstream: http://docs.unity3d.com/ScriptReference/BitStream.Serialize.html
Since our workarounds are quick and easy, it's not a big problem anyway :D
True that :D It's been a long time since I posted this, but I'm starting to remember the issue is .Net serialization. Oh well, ty for posting your solution, it's nice and simple :)
For the sake of those looking around the web for an answer (which this ANSWER comes close to the top), it's always better to serialize deconstructed types of data (int, floats, bools and Lists of those) than using more complexes features that requires to be run through the Engine's libraries.
The reason why things like Vectors and Colors aren't always supported is because their definition is relative and may varies between software while things like int, floats, bool and List of those are natively compatible with "any" OS due to them being basic types of data. (Something more basic would be binaries for instance.)
For some 2D software, a Vector can be deter$$anonymous$$ed as a line generated from 2 points (vertex) with 2 coordinates (x,y) each while in another like Unity, it's a simple point of coordinated. Same with Color as a value. In some software, a Color never means RGBA... Some even only consider WEB# colors. It's relative to what kind of library is being used.
Due to that, it's virtually impossible to impose a definition of those through standard native serialization of the data if it's get formatted (such as with binaryFormatter) into a simple format. If the native OS libraries were to do such a thing as define what "Vector" means and what "Color" means, it would turn at least half of the existing software obsolete by the next hour.