Serializing Rect with BinaryFormatter

I’m trying to use BinaryFormatter to serialize the data in a custom class to a Byte array. The BinaryFormatter doesn’t have a problem with most types, but I get an error from the Rect I have in my custom class saying that the Rect isn’t serializable. Should it be possible to serialize a Rect with BinaryFormatter, or does it only work on primative types?

Have a look at Surrogates and SurrogateSelector in the .net. Basically you need to provide a way how to serialize classes that are not marked as Serializable by an attribute. Your SurrogateSelector will return an appropriate surrogate for the given type, and the surrogate is an object that will represent your object (Rect in your case) in the serialization.
So your to-do list is:

  • Create a Surrogate for Rect. This object will receive your rect and SerializationInfo object, and it’s task s to do R/W between them
  • Create a SurrogateSelector. I don’t remember details, it’s been a time, but I think you can either implement your own, or use some existing implementation that selects surrogates based on object type. Return your RectSurrogate when serializing Rect
  • Provide your BinaryFormatter with an instance of the SurrogateSelector. I think you can do that in the constructor

Stick to the MSDN docs, ask if something is unclear
You may want to write surrogates for Vectors or other unity types too, and serialize Rect with its members as Vectors

Yo can create your own Serializable Class for Rect since you can create an instance with 4 floats (Unity - Scripting API: Rect.Rect ). Something like this: (Haven’t tested it, but should work)

[Serializable]
public class SerializableRect
{
    private float x;
    private float y;
    private float width;
	private float height;
	
        
    public SerializableRect(Rect MyRect)
    {
        x = MyRect.x;
        y = MyRect.y;
        width = MyRect.width;
		height = MyRect.height;
		
    }
    public override string ToString()
    {
        return String.Format("[{0}, {1}, {2}, {3}]", x, y, width, height);
    }


    /// Automatic conversion from SerializableRect to Rect
        public static implicit operator Rect(SerializableRect vRect)
    {
        return new Rect(vRect.x, vRect.y, vRect.width, vRect.height);
    }


    /// Automatic conversion from Rect to SerializableRect
    public static implicit operator SerializableRect(Rect vRect)
    {
        return new SerializableRect(vRect);
    }
}

You can use the class like this:

    private SerializableRect serRect;
    public Rect unityRect
    {
        get { return serRect; } //implicit conversion as defined in class
        set { serRect = value; }
    }