diff --git a/com.unity.netcode.gameobjects/CHANGELOG.md b/com.unity.netcode.gameobjects/CHANGELOG.md index 6922d1eeda..13f6126579 100644 --- a/com.unity.netcode.gameobjects/CHANGELOG.md +++ b/com.unity.netcode.gameobjects/CHANGELOG.md @@ -10,6 +10,9 @@ Additional documentation and release notes are available at [Multiplayer Documen ### Added +- Added `FastBufferReader(ArraySegment buffer, Allocator copyAllocator)` constructor that uses the `ArraySegment.Offset` as the `FastBufferReader` offset and the `ArraySegment.Count` as the `FastBufferReader` length. (#3321) +- Added `FastBufferReader(ArraySegment buffer, Allocator copyAllocator, int length = -1)` constructor that uses the `ArraySegment.Offset` as the `FastBufferReader` offset. (#3321) + ### Fixed - Fixed `OnClientConnectedCallback` passing incorrect `clientId` when scene management is disabled. (#3312) diff --git a/com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs b/com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs index bf30e04b4b..c856a6197b 100644 --- a/com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs +++ b/com.unity.netcode.gameobjects/Runtime/Serialization/FastBufferReader.cs @@ -140,6 +140,54 @@ public unsafe FastBufferReader(ArraySegment buffer, Allocator copyAllocato } } + /// + /// Create a FastBufferReader from an ArraySegment that uses the ArraySegment.Offset for the reader's offset. + /// + /// A new buffer will be created using the given allocator and the value will be copied in. + /// FastBufferReader will then own the data. + /// + /// Allocator.None is not supported for byte[]. If you need this functionality, use a fixed() block + /// and ensure the FastBufferReader isn't used outside that block. + /// + /// The buffer to copy from + /// The allocator type used for internal data when copying an existing buffer if other than Allocator.None is specified, that memory will be owned by this FastBufferReader instance + /// The number of bytes to copy (all if this is -1) + public unsafe FastBufferReader(ArraySegment buffer, Allocator copyAllocator, int length = -1) + { + if (copyAllocator == Allocator.None) + { + throw new NotSupportedException("Allocator.None cannot be used with managed source buffers."); + } + fixed (byte* data = buffer.Array) + { + + Handle = CreateHandle(data, length == -1 ? buffer.Count : length, buffer.Offset, copyAllocator, Allocator.Temp); + } + } + + /// + /// Create a FastBufferReader from an ArraySegment that uses the ArraySegment.Offset for the reader's offset and the ArraySegment.Count for the reader's length. + /// + /// A new buffer will be created using the given allocator and the value will be copied in. + /// FastBufferReader will then own the data. + /// + /// Allocator.None is not supported for byte[]. If you need this functionality, use a fixed() block + /// and ensure the FastBufferReader isn't used outside that block. + /// + /// The buffer to copy from + /// The allocator type used for internal data when copying an existing buffer if other than Allocator.None is specified, that memory will be owned by this FastBufferReader instance + public unsafe FastBufferReader(ArraySegment buffer, Allocator copyAllocator) + { + if (copyAllocator == Allocator.None) + { + throw new NotSupportedException("Allocator.None cannot be used with managed source buffers."); + } + fixed (byte* data = buffer.Array) + { + Handle = CreateHandle(data, buffer.Count, buffer.Offset, copyAllocator, Allocator.Temp); + } + } + /// /// Create a FastBufferReader from an existing byte array. /// diff --git a/com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs b/com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs index 30b1ba895b..020f7e6902 100644 --- a/com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs +++ b/com.unity.netcode.gameobjects/Tests/Editor/Serialization/FastBufferReaderTests.cs @@ -1579,5 +1579,21 @@ public unsafe void WhenCallingTryBeginReadInternal_AllowedReadPositionDoesNotMov Assert.AreEqual(reader.Handle->AllowedReadMark, 25); } } + + [Test] + public unsafe void WhenUsingArraySegment_ConstructorHonorsArraySegmentConfiguration() + { + var bytes = new byte[] { 0, 1, 2, 3 }; + var segment = new ArraySegment(bytes, 1, 3); + var reader = new FastBufferReader(segment, Allocator.Temp); + + var readerArray = reader.ToArray(); + Assert.True(readerArray.Length == bytes.Length - 1, $"Array of reader should have a length of {bytes.Length - 1} but was {readerArray.Length}!"); + for (int i = 0; i < readerArray.Length; i++) + { + Assert.True(bytes[i + 1] == readerArray[i], $"Value of {nameof(readerArray)} at index {i} is {readerArray[i]} but should be {bytes[i + 1]}!"); + } + reader.Dispose(); + } } }