Bitpacking
Obsolete: please use NetworkReader/Writer instead.
Bitpacking won't be necessary with the new delta compression.
NetworkReader/Writer are faster too.
DOTSNET uses Bitpacking via BitWriter to serialize, and BitReader to deserialize data down to the bit.
Usage
For example, this is how we serialize an int and a float3 position in a message:
using DOTSNET;
public struct TestMessage : NetworkMessage
{
public int classIndex;
public float3 position;
public byte GetID() => 0x31;
public bool Serialize(ref BitWriter writer) =>
writer.WriteInt(classIndex) &&
writer.WriteFloat3(position);
public bool Deserialize(ref BitReader reader) =>
reader.ReadInt(out classIndex) &&
reader.ReadFloat3(out position);
}Reading and Writing is:
Atomic:
WriteInteither writes all 4 bytesint, or none if there is not enough space.ReadInteither reads all 4 bytesint, or none if the buffer doesn’t have enough data.Allocation Free: all reads and writes are allocation free for maximum performance.
Fast: the Bitpacker’s internal buffer writes are always word aligned. This makes unaligned writes (
byte/ushort/etc.) as fast as aligned writes (uint,float, etc.).
Reference Passing
To avoid allocations, BitReader/Writer are value types (structs). When passing a reader/writer through functions, make sure to pass it as reference:
If you don’t pass it as reference, then it will create a copy of the Writer/Reader, which would not modify the original writer/reader’s Position.
In other words, always pass BitReader/Writer as reference!
Bit Compression
BitWriter/Reader default functions always write the full type unless bitpacking parameters are specified. For example, let’s serialize/deserialize a player’s level which requires 32 bits uint by default:
If we know the value’s minimum and maximum data range, then we can do heavy bandwidth optimizations by packing it into the minimum amount of bits needed for that range. Our player’s level is always in the range of [1..60] so we can Bitpack it down from 32 bits to 6 bits:
DOTSNET’s Bitpacking automatically does all the complicated bit math internally. All we need to do is specify the data type ranges if we know them.
This also works for float/double where we specify min, max, precision
Another interesting example is bool, which C# stores into 8 bit = 1 byte by default. A bool is always either 1 or 0, which fits perfectly into just 1 bit. DOTSNET packs bools automatically!
For a deeper understanding about Bitpacking, please read the excellent article by Glenn Fiedler!
Burst
DOTSNET BitReader/Writers are burstable.
Additionally, DOTSNET provides fixed size Readers/Writers for use in IComponentData:
BitReader128
BitWriter128
Extending BitReader/Writer
You can extend BitReader/Writer with C#’s extension system:
Last updated