Impossible to preserve property value when changing type

Issue #216 resolved
Former user created an issue

I have a generic container, Container<T> that contains a single data (reference or value type). If I have a MonoBehaviour property, eg. an int, and change it to Container<int>, all the previously serializied values are lost. Now I tried to make a custom DataFormatter, so it is serialized just as it would be without the container. But it seems to be not possible, because value and reference types are handled separately.

Is there any way I could acomplish this with Odin? It was possible with other frameworks.

First of all, there could be an option, that makes Odin serialize everything that Unity does. Yes, everything will be serialized twice, but rather this, than not being able to change the property type.

Second, can Container<int> be serialized as if it would be a simple int?

Comments (1)

  1. Tor Esa Vestergaard

    This actually works in almost all cases, if you declare implicit or explicit cast operators, like so:

    public class Container<T>
    {
        public T Value;
    
        public static explicit operator Container<T>(T value)
        {
            return new Container<T>() { Value = value };
        }
    
        public static explicit operator T(Container<T> value)
        {
            return value.Value;
        }
    }
    

    Now, the serialization system will know that T can convert to a type of Container<T>, and the reverse, and it will do so upon deserialization. This will only fail to work in the case of "primitive" types, since, for performance reasons, those work separately from the formatter system, with custom-written strongly-typed serializers for each, which don't use Odin's complex casting logic.

    The types which Odin's serialization considers primitives are checked with the following criteria: type.IsPrimitive or type.IsEnum, or type is a decimal, string or Guid. That is, if the type is a number, an enum, a string or a Guid, this will not work. In all other cases, it will.

    I'm afraid it will never come to work with said primitive types - the changes required are simply too drastic, and would probably wreck the performance of the serialization system.

    Otherwise, the following code will work with the above cast operators, with you switching back and forth between the two types, and all values being retained:

    [OdinSerialize]
    public Vector3 vec;
    //public Container<Vector3> vec;
    

    Edit: As for the option to simply make Odin serialize everything in a type by default, this is something we are considering adding, but there are certain nuances and complexities we need to consider thoroughly before we decide how exactly to implement this, as there are a few different variations of use cases that need to act differently.

  2. Log in to comment