Unity system.object serialization.

I have a object, that contains something of type system.object.

public class Foo : MonoBehaviour
{
  [SerializeField]
  object Val;
}

Val can contain primitives such as a float, a Vector3 or a Color.

Is there any way to get this to serialize properly?

Not without some extra fields which can actually store a supported serialized type. Unity serializes data based on the variable type. Since System.Object isn’t a supported type it won’t get serialized at all.

The best bet here would be to use the new ISerializationCallbackReceiver paired with a serialized string variable which holds the serialized data. How you serialize and deserialize your “object” is up to you as long as you can convert it into a string and be able to recreate the original value from that string you should be fine.

Here’s an (untested) example to support int, float, Color and Vector3 values:

public class Foo : MonoBehaviour, ISerializationCallbackReceiver
{
    // our value of interest
    private object val;
    
    [SerializeField, HideInInspector]
    private string valSerialized;
    
    public void OnBeforeSerialize()
    {
        if (val == null)
        {
            valSerialized = "n";
            return;
        }
        var type = val.GetType();
        if (type == typeof(int))
            valSerialized = "i"+val.ToString();
        else if (type == typeof(float))
            valSerialized = "f"+val.ToString();
        else if (type == typeof(Color))
        {
            Color32 c = (Color)val;
            uint v = (uint)c.r + (uint)c.g<<8 + (uint)c.b<<16 + (uint)c.a<<24;
            valSerialized = "c" + v;
        }
        else if (type == typeof(Vector3))
        {
            Vector3 v = (Vector3)val;
            valSerialized = "v" + v.x + "|" +v.y + "|" + v.z;
        }
    }
    
    public void OnAfterDeserialize()
    {
        if (valSerialized.Length == 0)
            return;
        char type = valSerialized[0];
        if (type == 'n')
            val = null;
        else if (type == 'i')
            val = int.Parse(valSerialized.SubString(1));
        else if (type == 'f')
            val = float.Parse(valSerialized.SubString(1));
        else if (type == 'c')
        {
            uint v = int.Parse(valSerialized.SubString(1));
            Color c = new Color32(v & 0xFF, (v>>8) & 0xFF, (v>>16) & 0xFF,(v>>24) & 0xFF);
            val = c;
        }
        else if (type == 'v')
        {
            string[] v = valSerialized.SubString(1).Split('|');
            val = new Vector3(float.Parse(v[0]), float.Parse(v[1]), float.Parse(v[2]));
        }
    }
}

Note: The deserialization has no checks if the string is in the required format. To actually use this you might want to implement some checks or at least enclose it in a try-catch block.

@Bunny83 :
Nice job! There were some small syntactical errors I removed, and I also added bool and Vector2. Moreover, I tested your solution and it works for all datatypes. Please find the updated and tested code below:

            [System.Serializable]
                public class ObjectSerializable : ISerializationCallbackReceiver
                {
                    public ObjectSerializable(object _val)
                    {
                        val = _val;
                    }
                    
                    // our value of interest
                    private object val;
            
                    [SerializeField, HideInInspector]
                    private string valSerialized;
            
            
                    public object GetValue()
                    {
                        return val;
                    }
            
                    public void OnBeforeSerialize()
                    {
                        if (val == null)
                        {
                            valSerialized = "n";
                            return;
                        }
                        var type = val.GetType();
                        if (type == typeof(int))
                            valSerialized = "i" + val.ToString();
                        else if (type == typeof(float))
                            valSerialized = "f" + val.ToString();
                        else if (type == typeof(Color))
                        {
                            Color32 c = (Color)val; 
                            uint v = (uint)c.r + ((uint)c.g << 8) + ((uint)c.b << 16) + ((uint)c.a << 24);
                            valSerialized = "c" + v;
                        }
                        else if (type == typeof(Vector2))
                        {
                            Vector2 v = (Vector2)val;
                            valSerialized = "w" + v.x + "|" + v.y;
                        }
                        else if (type == typeof(Vector3))
                        {
                            Vector3 v = (Vector3)val;
                            valSerialized = "v" + v.x + "|" + v.y + "|" + v.z;
                        }
                        else if(type == typeof(bool))
                        {
                            bool v = (bool)val;
                            valSerialized = "b" + v;
                        }
                    }
            
                    public void OnAfterDeserialize()
                    {
                        if (valSerialized.Length == 0)
                            return;
                        char type = valSerialized[0];
                        if (type == 'n')
                            val = null;
                        else if (type == 'i')
                            val = int.Parse(valSerialized.Substring(1));
                        else if (type == 'f')
                            val = float.Parse(valSerialized.Substring(1));
                        else if (type == 'c')
                        {
                            uint v = uint.Parse(valSerialized.Substring(1)); //
                            Color c = new Color32((byte) (v & 0xFF), (byte) ((v >> 8) & 0xFF), (byte) ((v >> 16) & 0xFF), (byte) ((v >> 24) & 0xFF));
                            val = c;
                        }
                        else if (type == 'w')
                        {
                            string[] v = valSerialized.Substring(1).Split('|');
                            val = new Vector2(float.Parse(v[0]), float.Parse(v[1]));
                        }
                        else if (type == 'v')
                        {
                            string[] v = valSerialized.Substring(1).Split('|');
                            val = new Vector3(float.Parse(v[0]), float.Parse(v[1]), float.Parse(v[2]));
                        }
                        else if(type == 'b')
                        {
                            val = bool.Parse(valSerialized.Substring(1));
                        }
                    }
                }