DeltaPack 0.2.1
dotnet add package DeltaPack --version 0.2.1
NuGet\Install-Package DeltaPack -Version 0.2.1
<PackageReference Include="DeltaPack" Version="0.2.1" />
<PackageVersion Include="DeltaPack" Version="0.2.1" />
<PackageReference Include="DeltaPack" />
paket add DeltaPack --version 0.2.1
#r "nuget: DeltaPack, 0.2.1"
#:package DeltaPack@0.2.1
#addin nuget:?package=DeltaPack&version=0.2.1
#tool nuget:?package=DeltaPack&version=0.2.1
DeltaPack for C#
Binary serialization library optimized for delta encoding of game state.
Installation
dotnet add package DeltaPack
Quick Start
using DeltaPack;
// Define your types
public class Player
{
public string Name { get; set; } = "";
public int Score { get; set; }
public bool Active { get; set; }
}
// Create a codec (do this once during initialization)
var codec = new DeltaPackCodec<Player>();
// Encode
var player = new Player { Name = "Alice", Score = 100, Active = true };
byte[] encoded = codec.Encode(player);
// Decode
Player decoded = codec.Decode(encoded);
Delta Encoding
Send only what changed between two states:
var stateA = new GameState { Score = 100, Health = 100 };
var stateB = new GameState { Score = 150, Health = 100 }; // Only score changed
byte[] diff = codec.EncodeDiff(stateA, stateB);
GameState result = codec.DecodeDiff(stateA, diff);
// diff is smaller than full encode when few fields change
Code Generation
As an alternative to reflection-based serialization, you can generate C# code from a YAML schema:
# schema.yml
Player:
name: string
score: int
active: boolean
GameState:
players: <string, Player>
round: uint
Generate C# code using the CLI:
delta-pack generate schema.yml -l csharp -o Generated.cs
The generated code provides static methods for each type:
// Generated types are plain classes
var player = new Player { Name = "Alice", Score = 100, Active = true };
// Static encode/decode methods
byte[] encoded = Player.Encode(player);
Player decoded = Player.Decode(encoded);
// Delta encoding
byte[] diff = Player.EncodeDiff(oldPlayer, newPlayer);
Player result = Player.DecodeDiff(oldPlayer, diff);
When to use codegen vs reflection:
- Codegen: Shared schemas across TypeScript/C#, compile-time type safety, no reflection overhead
- Reflection: Define types directly in C#, no build step, works with existing classes
Supported Types
- Primitives:
string,bool,int,uint,long,ulong,float,double,byte,short, etc. - Enums: Bit-packed using minimum bits needed (e.g., 4 variants = 2 bits)
- Collections:
List<T>,OrderedDictionary<TKey, TValue>(TKey:string,int,uint,long,ulong) - Nullable value types:
int?,float?, etc. - Nullable reference types:
Player?,string?, etc. - Nested objects: Any class with public properties
- Self-referencing types: Types that reference themselves (e.g., linked lists, trees)
- Union types: Abstract classes with
[DeltaPackUnion]attribute
Attributes
[DeltaPackPrecision]
Quantize floats for smaller encoding:
public class Position
{
[DeltaPackPrecision(0.01)]
public float X { get; set; }
[DeltaPackPrecision(0.01)]
public float Y { get; set; }
}
[DeltaPackRange]
Specify bounds for integers (enables more efficient encoding):
public class Stats
{
[DeltaPackRange(0, 100)]
public int Health { get; set; }
[DeltaPackRange(1)] // min only
public int PlayerId { get; set; }
}
[DeltaPackIgnore]
Exclude a property from serialization:
public class Player
{
public string Name { get; set; } = "";
public int Score { get; set; }
[DeltaPackIgnore]
public string CachedDisplayName { get; set; } = "";
}
[DeltaPackUnion]
Define polymorphic types:
[DeltaPackUnion(typeof(Sword), typeof(Bow))]
public abstract class Weapon
{
public string Name { get; set; } = "";
}
public class Sword : Weapon
{
public int SlashDamage { get; set; }
}
public class Bow : Weapon
{
public int ArrowDamage { get; set; }
public float Range { get; set; }
}
API Reference
DeltaPackCodec<T>
| Method | Description |
|---|---|
Encode(T obj) |
Serialize object to bytes |
Decode(byte[] buf) |
Deserialize bytes to object |
EncodeDiff(T a, T b) |
Encode only the differences between a and b |
DecodeDiff(T a, byte[] diff) |
Apply diff to a, producing b |
Equals(T a, T b) |
Deep equality comparison |
Clone(T obj) |
Deep clone |
FromJson(JsonElement json) |
Deserialize from JSON |
ToJson(T obj) |
Serialize to JSON |
Schema |
The generated schema (for debugging) |
Custom Factory
For types without parameterless constructors, such as records:
public record ImmutablePlayer(string Name, int Score);
var codec = new DeltaPackCodec<ImmutablePlayer>(
() => new ImmutablePlayer("", 0)
);
Note: Union types (abstract classes with
[DeltaPackUnion]) don't require a factory—variants are instantiated directly during decoding.
Unity Compatibility
This library targets netstandard2.1 and is compatible with Unity 2021.2+.
Recommended usage pattern:
public class NetworkManager : MonoBehaviour
{
// Create codecs once during initialization
private DeltaPackCodec<GameState> _stateCodec;
private DeltaPackCodec<PlayerInput> _inputCodec;
void Awake()
{
_stateCodec = new DeltaPackCodec<GameState>();
_inputCodec = new DeltaPackCodec<PlayerInput>();
}
void SendState(GameState state)
{
byte[] data = _stateCodec.Encode(state);
// Send data...
}
GameState ReceiveState(byte[] data)
{
return _stateCodec.Decode(data);
}
}
Requirements
Runtime
- .NET 6.0+ or .NET Standard 2.1 (Unity 2021.2+)
Type Definitions
- Parameterless constructor required (or provide a factory)
- Public properties with both getter and setter are serialized
- Public fields are also serialized
initsetters work (reflection bypasses compile-time restriction)- Private members are skipped
- Read-only properties (getter only) are skipped
- Dictionary keys must be
string,int,uint,long, orulong
public class Player
{
public string Name { get; set; } = ""; // ✓ Serialized
public int Score { get; init; } // ✓ Serialized (init works)
public int Health; // ✓ Serialized (public field)
public string Id { get; } // ✗ Skipped (no setter)
private int _internalId; // ✗ Skipped (private)
[DeltaPackIgnore]
public string CachedValue { get; set; } // ✗ Skipped (ignored)
}
Binary Format
Data layout: [field data][RLE bits][numRleBits: reverse varint]
- Integers use varint encoding (zigzag for signed)
- Booleans are collected and RLE-compressed at the end of the buffer
- Floats can be quantized to reduce precision and size
- Strings are length-prefixed UTF-8
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- System.Text.Json (>= 8.0.5)
- YamlDotNet (>= 16.2.1)
-
net10.0
- YamlDotNet (>= 16.2.1)
-
net6.0
- YamlDotNet (>= 16.2.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.