NetworkVariable fails to update when size greater 256 Bytes

Heyhey,

Today I tried to update the Unity NGO package to version 1.6.0 but I encountered this error:
Overflow Exception

OverflowException: Writing past the end of the buffer
Unity.Netcode.FastBufferWriter.WriteBytesSafe (System.Byte* value, System.Int32 size, System.Int32 offset) (at ./Library/PackageCache/com.unity.netcode.gameobjects@1.6.0/Runtime/Serialization/FastBufferWriter.cs:732)
Unity.Netcode.FastBufferWriter.WriteUnmanagedSafe[T] (Unity.Collections.NativeList1[T] value) (at ./Library/PackageCache/com.unity.netcode.gameobjects@1.6.0/Runtime/Serialization/FastBufferWriter.cs:1001) Unity.Netcode.FastBufferWriter.WriteValueSafe[T] (Unity.Collections.NativeList1[T] value, Unity.Netcode.FastBufferWriter+ForGeneric unused) (at ./Library/PackageCache/com.unity.netcode.gameobjects@1.6.0/Runtime/Serialization/FastBufferWriter.cs:1263)
Unity.Netcode.BufferSerializerWriter.SerializeValue[T] (Unity.Collections.NativeList1[T]& value, Unity.Netcode.FastBufferWriter+ForGeneric unused) (at ./Library/PackageCache/com.unity.netcode.gameobjects@1.6.0/Runtime/Serialization/BufferSerializerWriter.cs:41) Unity.Netcode.BufferSerializer1[TReaderWriter].SerializeValue[T] (Unity.Collections.NativeList1[T]& value, Unity.Netcode.FastBufferWriter+ForGeneric unused) (at ./Library/PackageCache/com.unity.netcode.gameobjects@1.6.0/Runtime/Serialization/BufferSerializer.cs:143) LargeByteList.NetworkSerialize[T] (Unity.Netcode.BufferSerializer1[TReaderWriter] serializer) (at Assets/Core/RTVR/Scripts/Netcode/DuplicateBugTester.cs:13)

This is only happening for NetworkVariable() but not for RPC calls.

After some investigation I think the problem lays with the Duplicate function in the ngopackage\Runtime\NetworkVariable\NetworkVariableSerialization.cs file. It does not allow the FastBufferWritter to scale beyond 256Bytes

        public void Duplicate(in T value, ref T duplicatedValue)
        {
            using var writer = new FastBufferWriter(256, Allocator.Temp);
            var refValue = value;
            Write(writer, ref refValue);

            using var reader = new FastBufferReader(writer, Allocator.None);
            Read(reader, ref duplicatedValue);
        }

Adding something like using var writer = new FastBufferWriter(256, Allocator.Temp, 65536); seems to fix the issue, but those files are immutable of course.

This is the code to reproduce the error:
Source code

using System;
using Unity.Collections;
using Unity.Netcode;
using UnityEngine;
[Serializable]
public class LargeByteList : INetworkSerializable
{
    //being filled with 1024 bytes
    const int targetByteCount = 1024;
    public NativeList<byte> bytes = new NativeList<byte>(Allocator.Persistent);
    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
        serializer.SerializeValue(ref bytes);
    }
    public void Fill()
    {
        for (int i = 0; i < targetByteCount; i++)
            bytes.Add(1);
    }
}
[Serializable]
public class LargeDecimalContainer : INetworkSerializable
{
    //sizeof(decimal) = 24 Bytes
    //18 * decimal => 288 Bytes
    public decimal x1, x2, x3, x4, x5, x6;
    public decimal y1, y2, y3, y4, y5, y6;
    public decimal z1, z2, z3, z4, z5, z6;
    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
        serializer.SerializeValue(ref x1);
        serializer.SerializeValue(ref x2);
        serializer.SerializeValue(ref x3);
        serializer.SerializeValue(ref x4);
        serializer.SerializeValue(ref x5);
        serializer.SerializeValue(ref x6);
        serializer.SerializeValue(ref y1);
        serializer.SerializeValue(ref y2);
        serializer.SerializeValue(ref y3);
        serializer.SerializeValue(ref y4);
        serializer.SerializeValue(ref y5);
        serializer.SerializeValue(ref y6);
        serializer.SerializeValue(ref z1);
        serializer.SerializeValue(ref z2);
        serializer.SerializeValue(ref z3);
        serializer.SerializeValue(ref z4);
        serializer.SerializeValue(ref z5);
        serializer.SerializeValue(ref z6);
    }
    public void Fill()
    {
        const decimal value = decimal.MaxValue;
        x1 = x2 = x3 = x4 = x5 = x6 = value;
        y1 = y2 = y3 = y4 = y5 = y6 = value;
        z1 = z2 = z3 = z4 = z5 = z6 = value;
    }
}
class DuplicateBugTester : NetworkBehaviour
{
    public NetworkVariable<LargeByteList> largeByteList = new NetworkVariable<LargeByteList>(new LargeByteList());
    public NetworkVariable<LargeDecimalContainer> largeDecimalContainer = new NetworkVariable<LargeDecimalContainer>(new LargeDecimalContainer());
    public override void OnNetworkSpawn()
    {
        largeByteList.Value.Fill();
        largeDecimalContainer.Value.Fill();
    }
}

Have a nice day :slight_smile:

I suspect NetworkVariable isn’t designed for “large” amounts of data.
Specifically considering that it would likely send out the entire 256 bytes on every change. Is that really what you need and want to do? Because that can quickly amount to significant bandwidth if you’re not careful.

The right way to go about this is to implement the INetworkSerializable (recalled from memory) interface and use that to serialize your custom class.

But pretty sure you do NOT want to send the whole thing(-ies?) around on every change. :wink:
And if this is a one-time (or rare) thing, it shouldn’t be a NetworkVariable to begin with.

I agree to some extend. Since it was working before and I could not find any limitation information within the documentation I thought this might not be intended. The use case I got are relatively large level informations which only get changed when switching the level. Having this within a NetworkVariable was a pretty easy way to do it. But yea I ll just change to some RPC back and forth for now i guess :slight_smile: