Open barrrettt opened 8 months ago
The [Serializable]
attribute is only used for binary serialization which can be dangerous and not recommended. I feel like .NET has moved away from the attribute: The new System.Text.Json
doesn't use it, they provide their own custom attributes for serialization or users can create custom converters. The vector types in System.Numerics
also don't use the attribute.
If you are using the Godot Multiplayer APIs, these types should already be serialized correctly when sending them, your class needs to derive from GodotObject
(more specifically, you probably want to derive Resource
here) and annotate the properties with the [Export]
attribute as needed.
It's also possible that whatever you are using for serialization allows to provide custom converters, or you can create a custom Vector3DTO
type to be used in your DTOs instead of the real Vector3
type. You may also be interested in using the GD.VarToBytes
/GD.BytesToVar
and GD.VarToStr
/GD.StrToVar
APIs that allow you to convert Variants (like Vector3
) into an array of bytes or a string in a way that can be converted back into the original Variant type.
Iam with .net 6.0 [Serializable] work with JSON. look:
Finally
using System;
using System.Collections.Generic;
using Godot;
[Serializable]
public class CharacterHumanoidData{
public string PlayerToken { get; set; }
public int NetId { get; set; }
public string Name { get; set; }
public Color Color { get; set; }
public int Aspect { get; set; }
//this for Vector3
public string PlayerPositionSerialized { get; set; }
public CharacterHumanoidData(){
//randomiza a color
List<Color> colors = new() {
new(0.988f, 0.741f, 0.698f),
new(0.47f, 0.328f, 0.281f),
new(0.267f, 0.177f, 0.147f),
new(0.925f, 0.416f, 0.373f),
new(0.982f, 0.778f, 0.511f),
};
Random rnd = new();
int iColor = rnd.Next(0, colors.Count);
Color = colors[iColor];
//zero position
SetPlayerPosition(Vector3.Zero);
}
//getter+setter for des/serialize vectors3
public void SetPlayerPosition(Vector3 position){
PlayerPositionSerialized = $"{position.X};{position.Y};{position.Z}";
}
public Vector3 GetPlayerPosition(){
string[] parts = PlayerPositionSerialized.Split(';');
if (parts.Length == 3 &&
float.TryParse(parts[0], out float x) &&
float.TryParse(parts[1], out float y) &&
float.TryParse(parts[2], out float z))
{
return new Vector3(x, y, z);
}
return new();
}
}
It would be good if Vector3 were serializable, and not having to do this kind of hacks.
Vector3
has [Serializable]
so I'm not sure what you are missing here to make it work
Color works. why vector3 not?
Are you sure you're doing things right? Because they have the same setup
look: i change to Vector3 again
and print
result:
May be a bug?
As you can see the serialization of Color
isn't correct either as it saves multiple, mutually overlapping, values like both RGB and HSV/L, so it isn't working correctly for this setup with that either
You're right. The color is serialized in a strange way. RGBA should be sufficient. In my tests, the color was cloned correctly between pairs, so I hadn't noticed. Could it be some kind of bug in the mapping functions of these classes? I don't have any unusual configuration, I simply use [Serializable].
Irs probably just that the [Serializable]
tag isn't reliable or safe as pointed out above and you should use your own methods for it instead to be safe
System.Text.Json
ignores the System.Runtime.Serialization
attributes (see https://github.com/dotnet/runtime/issues/29975). It serializes all public members by default, regardless of whether the class is annotated with the [Serializable]
attribute or not. You can customize the serialization using custom converters or contracts.
It's worth noting that the [Serializable]
attribute will eventually be marked obsolete: https://github.com/dotnet/designs/blob/main/accepted/2020/better-obsoletion/binaryformatter-obsoletion.md
Yep. [Serializable] is not necessary for jsons. and some examples: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/how-to?pivots=dotnet-8-0
For those searching for copy/paste-able code, here is a quick converter I wrote based on @raulsntos's comments in this thread that you're welcome to use (consider it MIT-licensed):
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using Godot;
public class Vector2Converter : JsonConverter<Vector2>
{
public override Vector2 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return GD.StrToVar(reader.GetString()).AsVector2();
}
public override void Write(Utf8JsonWriter writer, Vector2 value, JsonSerializerOptions options)
{
writer.WriteStringValue(GD.VarToStr(value));
}
}
The resulting JSON value will look like this: "Vector2(78.4229, -36.6107)"
.
Don't forget to actually use the converter when serializing and deserializing:
JsonSerializerOptions options =
new()
{
WriteIndented = true,
Converters = { new Vector2Converter(), }
};
// JsonSerializer.Serialize(yourData, options);
// or
// JsonSerializer.Deserialize<YourData>(jsonString, options)
Describe the project you are working on
Multiplayer with c# I need send DTOs.
Describe the problem or limitation you are having in your project
my case: I need to send a DTO to the Networking Peers, like this one:
Describe the feature / enhancement and how it helps to overcome the problem or limitation
I believe that some types like Vector3, Vector2, Transform... should be able to be serialized.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
put [Serializable] in top of class Vector3 (Object?) š
If this enhancement will not be used often, can it be worked around with a few lines of script?
I have to do a hack like this one.
Is there a reason why this should be core and not an add-on in the asset library?
Vector3, Vector2, Transform.. are core clases
Thanks! š