I am unable to customize the serialization structure

My Unity version is 2023.2.17, and the Netcode version is 1.8.1

I refer to this article Custom serialization | Unity Multiplayer Networking To perform custom serialization extensions, I need to serialize some Structs from external libraries. However, even if I follow the corresponding definitions in the documentation, there will still be issues during compilation I tried to define any custom Struct but failed, but when I adjusted the data structure to Class, it could be successfully serialized. What is the reason for this?

#nullable enable
using Unity.Netcode;

public static class SerializationExtensions
{
    public static void ReadValueSafe(this FastBufferReader reader, out MyStruct value)
    {
        ByteUnpacker.ReadValuePacked(reader, out int i);
        value = new MyStruct { Value = i };
    }

    public static void WriterValueSafe(this FastBufferWriter writer, in MyStruct value)
    {
        BytePacker.WriteValuePacked(writer, value.Value);
    }
   
    public static void ReadValueSafe(this FastBufferReader reader, out MyClass value)
    {
        ByteUnpacker.ReadValuePacked(reader, out int i);
        value = new MyClass { Value = i };
    }

    public static void WriteValueSafe(this FastBufferWriter writer, in MyClass value)
    {
        BytePacker.WriteValuePacked(writer, value.Value);
    }
}

public struct MyStruct
{
    public int Value;
}

public class MyClass
{
    public int Value;
}
#nullable enable
using Unity.Netcode;
using UnityEngine;

public partial class Test : NetworkBehaviour
{

    [Rpc(SendTo.Everyone)]
    private void TestRpc(MyClass value) // It works
    {
        Debug.Log($"value: {value}");
    }

    [Rpc(SendTo.Everyone)]
    private void TestRpc(MyStruct value) // It not works
    {
        Debug.Log($"value: {value}");
    }
}

RTFM :wink:

MyStruct does not implement the INetworkSerializable interface.

Classes cannot be serialized, this probably just fails silently for the same reason: it doesn’t implement INetworkSerializable. So there’s probably no “is this a value type” check running.

I am well aware that serialization of a Structure can be achieved by inheriting INetworkSerializable or INetworkSerializeByMemcpy, but my current problem is that I need to serialize a structure from another library I am using, which I cannot change its inherited interface type. I can only try to serialize it in some ways

The first method is to use a Wrapper Struct to wrap the data in this Struct, transfer it, and then restore it Although this can achieve the desired effect, it requires additional processing when sending and receiving Rpcs. I don’t like this method

The second one is the method I saw in the Netcode article, which allows Netcode to collect this serialization method by defining extension methods. The defined objects can be serialized and deserialized during Rpc sending without inheriting INetworkSerializable, and it explains that custom serialization has a higher priority than INetworkSerializable

My problem now is that I can only serialize the class using this method. If I serialize the struct, it will report an error and cannot collect the corresponding extension method

I am well aware that serialization of a Structure can be achieved by inheriting INetworkSerializable or INetworkSerializeByMemcpy, but my current problem is that I need to serialize a structure from another library I am using, which I cannot change its inherited interface type. I can only try to serialize it in some ways

The first method is to use a Wrapper Struct to wrap the data in this Struct, transfer it, and then restore it Although this can achieve the desired effect, it requires additional processing when sending and receiving Rpcs. I don’t like this method

The second one is the method I saw in the Netcode article, which allows Netcode to collect this serialization method by defining extension methods. The defined objects can be serialized and deserialized during Rpc sending without inheriting INetworkSerializable, and it explains that custom serialization has a higher priority than INetworkSerializable

My problem now is that I can only serialize the class using this method. If I serialize the struct, it will report an error and cannot collect the corresponding extension method

9806865--1408218--upload_2024-5-1_15-58-6.png

9806865--1408221--upload_2024-5-1_15-58-15.png

Then I also tested the serialization method of MyClass, an extension method, and it worked properly without any issues.
I just want to know why the same extension method doesn’t work on Struct

I’m sorry, I didn’t get the full scope of the situation.

I believe the clue is in this statement:

Try adding a managed type such as an object to MyStruct to see if that works. If so, that would indicate the system is intended to be used only for types that are or contain at least one managed type.

I have adjusted the code to this, but it still cannot be compiled. It is still the same issue as before, and it cannot find the serialization method for MyStruct

#nullable enable
using Unity.Netcode;

public static class SerializationExtensions
{
    public static void ReadValueSafe(this FastBufferReader reader, out MyStruct value)
    {
        reader.ReadValueSafe(out int i);
        reader.ReadValueSafe(out int j);
        value = new MyStruct { Value = i, MyClass = new MyClass { Value = j } };
    }

    public static void WriterValueSafe(this FastBufferWriter writer, in MyStruct value)
    {
        writer.WriteValueSafe(value.Value);
        writer.WriteValueSafe(value.MyClass?.Value ?? 0);
    }

    public static void ReadValueSafe(this FastBufferReader reader, out MyClass value)
    {
        reader.ReadValueSafe(out int i);
        value = new MyClass { Value = i };
    }

    public static void WriteValueSafe(this FastBufferWriter writer, in MyClass value)
    {
        writer.WriteValueSafe(value.Value);
    }
}

public struct MyStruct
{
    public int Value;
    public MyClass? MyClass;
}

public class MyClass
{
    public int Value;
}

9806949--1408245--upload_2024-5-1_16-38-16.png

This may be a limitation of the system because it may assume you only need to use it on managed types, whereas unmanaged types can simply use INetworkSerializable (except as in your case).

But if you add MyStruct to MyClass you have achieved your goal. :wink:

You could also inspect the code that’s calling these ReadValueSafe methods to see if they have a separate code path for unmanaged types.

I can’t see why this isn’t working. As a possible alternative you could try ForceNetworkSerializeByMemcpy if the struct implements IEquatable.

1 Like