Description
The Duplicate method in UnmanagedNetworkSerializableSerializer causes errors when handling types that implement IDisposable due to pure assignment. This leads to issues such as multiple Dispose calls on NativeArray, resulting in runtime errors.
Reproduce Steps
- Create a struct that implements
IDisposable and INetworkSerializable. - Use this struct as a type for a
NetworkVariable. - Perform operations that involve serialization and deserialization of this struct.
- Observe the errors related to multiple
Dispose calls.
Actual Outcome
When using a struct that implements IDisposable with NetworkVariable, the Duplicate method causes multiple Dispose calls on NativeArray, leading to runtime errors and instability.
Expected Outcome
The Duplicate method should handle types that implement IDisposable correctly, ensuring that Dispose is called only once, avoiding multiple Dispose calls and ensuring stable runtime behavior.
Environment
- OS: [e.g. macOS Monterey]
- Unity Version: [e.g. 2023.1.20]
- Netcode Version: [e.g. 1.9.1]
Additional Context
Example of the problematic class:
publicstructNativeArray2D<T>:IDisposable,INetworkSerializablewhereT: unmanaged
{privateint_width;privateint_height;privateNativeArray<T>_array;publicNativeArray<T>.ReadOnlyRawArray=>_array.AsReadOnly();publicreadonlyintWidth=>_width;publicreadonlyintHeight=>_height;publicintLength=>_array.Length;publicNativeArray2D(intwidth,intheight,Allocatorallocator){_array=newNativeArray<T>(width*height,allocator);_width=width;_height=height;}publicNativeArray2D(intwidth,intheight,Allocatorallocator,TdefaultValue):this(width,height,allocator){for(vari=0;i<_array.Length;i++){_array[i]=defaultValue;}}publicTthis[intx,inty]{get=>_array[x+y*Width];set=>_array[x+y*Width]=value;}publicvoidDispose(){_array.Dispose();_array=default;}publicvoidNetworkSerialize<T1>(BufferSerializer<T1>serializer)whereT1:IReaderWriter{serializer.SerializeValue(ref_width);serializer.SerializeValue(ref_height);if(serializer.IsWriter){if(_array.IsCreated){serializer.GetFastBufferWriter().WriteValueSafe(true);serializer.SerializeValue(ref_array,Allocator.Persistent);}else{serializer.GetFastBufferWriter().WriteValueSafe(false);}}else{serializer.GetFastBufferReader().ReadValueSafe(outboolisCreated);if(isCreated){serializer.SerializeValue(ref_array,Allocator.Persistent);}}}}Solution
The current implementation of the Duplicate method in UnmanagedNetworkSerializableSerializer does not handle disposable types correctly because it uses pure assignment. To address this issue, consider using UserNetworkVariableSerialization's Duplicate method if available, or implement a custom serialization mechanism similar to the managed approach. For example:
if(UserNetworkVariableSerialization.Duplicate!=null){returnUserNetworkVariableSerialization.Duplicate(value);}else{usingvarwriter=newFastBufferWriter(256,Allocator.Temp,int.MaxValue);varrefValue=value;Write(writer,refrefValue);usingvarreader=newFastBufferReader(writer,Allocator.None);Read(reader,refduplicatedValue);returnduplicatedValue;}Disposable structs, even if unmanaged, should be handled separately to ensure proper resource management. This prevents issues related to multiple Dispose calls and ensures stable operation of the networked application.
Description
The
Duplicatemethod inUnmanagedNetworkSerializableSerializercauses errors when handling types that implementIDisposabledue to pure assignment. This leads to issues such as multipleDisposecalls onNativeArray, resulting in runtime errors.Reproduce Steps
IDisposableandINetworkSerializable.NetworkVariable.Disposecalls.Actual Outcome
When using a struct that implements
IDisposablewithNetworkVariable, theDuplicatemethod causes multipleDisposecalls onNativeArray, leading to runtime errors and instability.Expected Outcome
The
Duplicatemethod should handle types that implementIDisposablecorrectly, ensuring thatDisposeis called only once, avoiding multipleDisposecalls and ensuring stable runtime behavior.Environment
Additional Context
Example of the problematic class:
Solution
The current implementation of the
Duplicatemethod inUnmanagedNetworkSerializableSerializerdoes not handle disposable types correctly because it uses pure assignment. To address this issue, consider usingUserNetworkVariableSerialization'sDuplicatemethod if available, or implement a custom serialization mechanism similar to the managed approach. For example:Disposable structs, even if unmanaged, should be handled separately to ensure proper resource management. This prevents issues related to multiple Dispose calls and ensures stable operation of the networked application.