2

Following the answers to How to serialize a closed immutable type with protobuf-net and Protobuf-net and Unity3D types, I've tried implementing a serializer that can handle UnityEngine's Vector3 container, the only important values of which are Vector3.x, Vector3.y and Vector3.z:

Using the following TypeModel:

serializer = TypeModel.Create();
serializer.UseImplicitZeroDefaults = false;

Then I tried two different methods, separately, of adding a protocol definition for Vector3; an explicit definition:

serializer.Add(typeof(Vector3), false).Add(1, "x").Add(2, "y").Add(3, "z");

And using a surrogate:

serializer.Add(typeof(Vector3), false).SetSurrogate(typeof(SurrogateVector3));

With surrogate class:

[ProtoContract]
public sealed class SurrogateVector3
{
    [ProtoMember(1)]
    float x; 
    [ProtoMember(2)]
    float y; 
    [ProtoMember(3)]
    float z;

    public SurrogateVector3()
    {}

    public SurrogateVector3(float x, float y, float z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    public static implicit operator Vector3(SurrogateVector3 v)
    {
        return new Vector3(v.x, v.y, v.z);
    }

    public static implicit operator SurrogateVector3(Vector3 v)
    {
        return new SurrogateVector3(v.x, v.y, v.z);
    }
}

When using either method to try and serialize a Dictionary<int, Vector3>, the following exception is thrown:

NotSupportedException: Type cannot be represented as a default value: UnityEngine.Vector3
ProtoBuf.Serializers.DefaultValueDecorator.EmitBranchIfDefaultValue (ProtoBuf.Compiler.CompilerContext ctx, ProtoBuf.Compiler.CodeLabel label) (at <5e93d5bf6f2048709aab19aea88deb74>:0)
...

I'm unsure of how to modify my Typemodel or protocol definitions in order to successfully serialize collections of UnityEngine.Vector3.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900

1 Answers1

5

That's probably a bug in the "map" code, which needs fixing. You can probably avoid it for now by adding:

[ProtoMap(DisableMap = true)]

to the property/field that is the dictionary. The difference between the "map" code and the original pre-"map" code is subtle and not very interesting - it mostly changes what happens in the case of duplicates - but: it would seem that there's an annoying bug in the "map" logic, that probably doesn't exist in the original code path. However, the "map" path is now the default, hence the workaround of disabling it.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • I encoutered the same bug with a property defined like this: public Dictionary> Workflows { get; set; } – Dunge Jul 10 '19 at 18:56