Network Serialization & Delta Compression
π¦ Network Serialization & Delta Compression
In multiplayer game development, bandwidth is a strict physical budget. The standard Ethernet Maximum Transmission Unit (MTU) is 1,500 bytes. To avoid IP-level packet fragmentation (which causes catastrophic packet loss over UDP), game developers keep UDP packet sizes under 1,200 to 1,400 bytes.
If you send raw uncompressed C++ or Odin structs with 32-bit floats for every position, rotation, and velocity for 64 players at 60Hz, you will quickly saturate the player's connection.
Efficient netcode uses Bit-Packing, Float Quantization, and Delta Compression.
ποΈ 1. Bit-Packing (Working at the Bit Level)
Standard programming languages align variables to byte or 4-byte boundaries. In networking, we throw byte alignment away and treat packets as continuous bit streams:
| Data | Standard Size | Bit-Packed Size | Savings |
|---|---|---|---|
Boolean (is_crouching) | 1 byte (8 bits) | 1 bit | 87.5% |
| Weapon Slot (1 of 4 weapons) | 4 bytes (32 bits) | 2 bits ( | 93.7% |
| Health Points (0 to 100) | 4 bytes (32 bits) | 7 bits ( | 78.1% |
| Yaw Facing (0Β° to 360Β°) | 4 bytes (32 bits) | 9 bits ( | 71.8% |
Using a custom BitWriter and BitReader, multiple fields are packed consecutively into a byte buffer without padding.
π 2. Float Quantization (Compressing 3D Math)
Standard f32 floats allocate 1 sign bit, 8 exponent bits, and 23 mantissa bits (see Odin Precision Limits). Most game positions do not need sub-millimeter precision across infinite ranges.
The Quantization Formula
If a world coordinate is bounded between a minimum and maximum range
- Position Example: A level
using a 16-bit integer gives resolution. That cuts bandwidth in half compared to raw f32.
The "Smallest Three" Quaternion Compression
A full quaternion has 4 floats (x, y, z, w), totaling 128 bits.
Because normalized quaternions satisfy
- Find the component with the largest absolute value (0, 1, 2, or 3).
- Store its index in 2 bits.
- Negate the quaternion if the largest component is negative (ensuring the largest is always positive).
- Quantize the remaining 3 components into 9 bits each (range
). - Total size:
(down from 128 bitsβa 77% reduction!).
π 3. Delta Compression (Only Send What Changed)
Instead of sending the full game state every tick (Keyframe / Baseline), the server sends only the differences (Deltas) relative to the last state that the client confirmed receiving.
Client ACK history: "I received Server Snapshot #40"
Server prepares: Snapshot #45
Delta Packet = Difference between (Snapshot #45) and (Snapshot #40)
The Change Mask (Bitmask)
A single entity might have 20 networked properties (health, ammo, position, velocity, weapon, stance).
At the start of the entity stream, the server writes a Bitmask indicating which properties changed:
[ Change Mask: 0b00000101 ] -> Bits 0 and 2 are active
- Bit 0 active: Read Quantized Position (32 bits)
- Bit 1 inactive: Position Z unchanged (skip)
- Bit 2 active: Read Health (7 bits)
- Remaining bits inactive: All other properties remain identical to Snapshot #40!
If an entity is standing still, its update cost drops to a few bits instead of dozens of bytes.
π οΈ Engine Implementations & Best Practices
In Odin
Use #packed structs and explicit sized types for deterministic packet layouts (see Types in Odin):
Packet_Header :: struct #packed {
protocol_id: u32,
sequence: u16,
ack: u16,
ack_bitfield:u32, // Up to 32 previous acks in a single integer
}
In Unreal Engine 5
Unreal provides high-level tools to control replication bandwidth:
- Net Dormancy (
DORM_DormantAll): Tells the NetDriver to stop checking an Actor for changes entirely until awakened (huge CPU and bandwidth savings for static doors or dropped loot). NetUpdateFrequency: Limits how many times per second an Actor replicates (e.g., 20Hz for players, 2Hz for distant AI).- PushModel Networking: In UE5, replaces brute-force property polling by marking properties "dirty" only when they are actively modified in C++.
π Related Notes
- Basics Of NetWorking β UDP, TCP, and reliable messaging layers.
- Client-Side Prediction & Server Reconciliation β Replaying inputs and synchronizing client state.
- Types β Struct alignment and
#packeddata for binary serialization. - Precision β Integer limits and IEEE 754 floating-point characteristics.
- Index for Unreal β Unreal Engine C++ architecture.
- Game Development Hub β Central game development index.