Internally, the MLAPI uses Streams for it's data. This gives a ton of flexibility for the end user. If the end user for example doesn't want to use Streams but rather just byte arrays at their own level. They can do so by wrapping their arrays in MemoryStreams which don't create any garbage.
The MLAPI does have its own prefered Stream that is used internally called
NetworkBuffer is a Stream implementation that functions in a similar way as the
MemoryStream. The main difference is that the
NetworkBuffer has methods for operating on the Bit level rather than the Byte level.
NetworkBuffers allocates a byte array to back it, just like a
MemoryStream. To not create any allocations, the MLAPI has a built in Pool of
NetworkBuffers which is recommended to be used instead.
BinaryWriter class built into .NET is great for reading and writing binary data, it's not very compact or efficient and doesn't offer a ton of flexibility. The
NetworkReader solves this.
NetworkReader can operate at the bit level when used with a
NetworkBuffer . It also has many fancy write methods for compacting data.
Some of it's key features include the following.
When using the "Packed" versions of a write or read, the output will be VarInted. That is, smaller values will take less space. If you write the value 50 as a ulong in the packed format, it will only take one byte in the output.
When using the "Diff" versions of an array write or read, the output will be the diff between two arrays, allowing for delta encoding.
NetworkReader support many data types by default such as Vector3, Vector2, Ray, Quaternion and more.
If you for example have an enum with 5 values. All those values could fit into 3 bits. With the
NetworkWriter, this can be done like this:
When the stream is not aligned, (BitAligned == false, this occurs when writing bits that do fill the whole byte, or when writing bools as they are written as bits), performance is decreased for each write and read. This is only a big concern if you are about to write a large amount of data after not being aligned. To solve this, the
NetworkWriter allows you to "WritePadBits" and the
NetworkReader then lets you skip those bits with "SkipPadBits" to align the stream to the nearest byte.
The writer and reader also has pooled versions to avoid allocating the classes themselves. You might as well use them.