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 :slight_smile:

[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 *= 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 = 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!

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…

Hmmm, maybe you need to use SerializeField, or if it doesn’T work anyway, just store the rgba values as seperate floats :wink:

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 _= mainColor*; }*_

* }*

* public Color SecondColor {*
* get { return secondColor; }*
* set { secondColor = value;*
* for(int i = 0; i < 4; ++i)*
MyStats.secondColorArr = secondColor*; }*
* }*
}

[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 :smiley: Of course its weird to have getters/setters for public variables, but I need it for debugging in editor.

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 SurrogateSelector Class (System.Runtime.Serialization) | Microsoft Learn

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.

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 :slight_smile:

Hey, old post but I had the same issue, i post for futur people dealing with this. Here is what I did (pretty similar) :
I override the Unity Color class with a custom class for colors I want to serialize

[Serializable]
public class ColorSaver
{
    public float r, g, b, a;

    public ColorSaver(Color color)
    {
        r = color.r;
        g = color.g;
        b = color.b;
        a = color.a;
    }    
    
    public Color color()
    {
        return new Color(r, g, b, a);
    }

}

GameObject Serializer Pro supports serialization of Color, Color32, and much more (even entire textures and other subclasses of UnityEngine.Object)

Check the documentation for a list of all supported types