SetNet.StateSync
1.2.0
dotnet add package SetNet.StateSync --version 1.2.0
NuGet\Install-Package SetNet.StateSync -Version 1.2.0
<PackageReference Include="SetNet.StateSync" Version="1.2.0" />
<PackageVersion Include="SetNet.StateSync" Version="1.2.0" />
<PackageReference Include="SetNet.StateSync" />
paket add SetNet.StateSync --version 1.2.0
#r "nuget: SetNet.StateSync, 1.2.0"
#:package SetNet.StateSync@1.2.0
#addin nuget:?package=SetNet.StateSync&version=1.2.0
#tool nuget:?package=SetNet.StateSync&version=1.2.0
<p align="center"> <img src="https://raw.githubusercontent.com/Povstalez/SetNet/master/assets/icon.png" alt="SetNet" width="96"> </p>
SetNet.StateSync
Server-authoritative entity replication for SetNet.
Stream a world of entities from an authoritative server to clients with fixed-rate, delta-compressed snapshots over the unreliable channel, reliable spawns/despawns, client-side interpolation, interest management, and an input channel for client prediction. The core is engine-agnostic — it runs on a headless dedicated server and any .NET client. For Unity, add SetNet StateSync for Unity (NetworkObject/NetworkTransform/NetworkAnimator/NetworkRigidbody).
Composition, no base class. Depends only on SetNet.
Install
dotnet add package SetNet
dotnet add package SetNet.StateSync
At startup (both ends): register a serializer, call StateSyncRuntime.Enable(), and register your archetype schemas identically.
SetNetSerializer.Use(new MessagePackNetSerializer());
StateSyncRuntime.Enable();
const ushort Player = 1;
ReplicaRegistry.Register(ReplicaSchema.Create(Player)
.Field(FieldType.Vector3, interpolate: true, precision: 0.001f) // 0: position (quantized to mm)
.Field(FieldType.Quaternion, interpolate: true) // 1: rotation
.Field(FieldType.Float, interpolate: true) // 2: health
.Build());
Server
var world = server.UseStateSync(new StateSyncOptions { TickRate = 30 });
// spawn + mutate fields whenever; the tick samples them
var e = world.Spawn(Player, owner: peerId);
e.SetVec3(0, new Vec3(x, y, z));
e.SetQuat(1, rotation);
e.SetFloat(2, 100);
world.InputReceived += (peer, seq, payload) => { /* apply owned-entity input */ };
By default every connecting peer becomes an observer. Set StateSyncOptions.AutoObserve = false and call world.AddObserver(peer) yourself once a player is truly ready (e.g. after auth or joining a room), so you don't replicate the game to peers still in the lobby.
Client
var repl = client.UseStateSync(new StateSyncOptions { InterpolationDelayMs = 100 });
repl.EntitySpawned += view => { /* create your object for view.NetId / view.ArchetypeId */ };
repl.EntityDespawned += view => { /* destroy it */ };
// each frame:
repl.Update(); // advance interpolation
foreach (var v in repl.Entities)
{
var pos = v.GetVec3(0); // interpolated
var rot = v.GetQuat(1);
}
// owned-entity input for prediction:
var seq = repl.SendInput(inputBytes);
var acked = repl.LastProcessedInput; // reconcile against this
How it works
- Delta compression: each snapshot carries only the fields that changed since the client's acknowledged baseline (Quake-3-style tick/baseline history). A new or re-entering entity is sent full, then deltas. Lost snapshots self-heal on the next tick.
- Reliable lifecycle, unreliable state: spawns/despawns ride the reliable channel (
Both-mode TCP); snapshots ride unreliable UDP. On a TCP-only transport everything is reliable/ordered and it still works. - Interpolation: the client renders
InterpolationDelayMsbehind the newest snapshot, lerping floats/vectors and nlerp-ing quaternions between buffered samples. Set the delay to 0 to snap to the latest. - Interest management:
StateSyncOptions.Interestdecides what each observer sees.AllInterest(default) orDistanceInterest(area-of-interest), or your ownIInterestManager. Entities entering/leaving an observer's set are spawned/despawned for them. - Quantization: give a float/vector field a
precisionto send it as a scaled integer (smaller packets).
Options
| Option | Default | Meaning |
|---|---|---|
TickRate |
30 |
Snapshots per second |
InterpolationDelayMs |
100 |
Render delay for smoothing (0 = snap) |
MaxSnapshotHistory |
32 |
Delta baseline history depth |
Interest |
AllInterest |
Per-observer visibility |
AutoObserve |
true |
Auto-observe peers on connect |
Notes
- Node-local (entities are live objects on one server node). A multi-node setup shards worlds or hands players between nodes.
- UDP snapshots are unauthenticated at the packet level — put auth over the reliable channel (
SetNet.Auth), and use TLS/Bothfor sensitive data. - Reserved wire types
65518–65522.
Documentation & source
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. 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 was computed. 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
- SetNet (>= 1.2.0)
NuGet packages (8)
Showing the top 5 NuGet packages that depend on SetNet.StateSync:
| Package | Downloads |
|---|---|
|
SetNet.Godot
Godot 4 (C#) helpers for SetNet: a main-thread dispatcher to marshal background handler callbacks onto Godot's main thread (drain in _Process), and conversions between SetNet.StateSync math and Godot Vector2/Vector3/Quaternion. Depends on SetNet + SetNet.StateSync + GodotSharp. |
|
|
SetNet.StateSync.Rpc
Entity-scoped RPCs for SetNet.StateSync: send a method call tagged with a NetId to a specific client (server to client) or to the server (client to owned entity). server.UseStateSyncRpc() / client.UseStateSyncRpc(). Depends on SetNet + SetNet.StateSync. |
|
|
SetNet.StateSync.Godot
Godot 4 (C#) components for SetNet state replication: NetworkObject + NetworkTransform / NetworkRigidBody / NetworkAnimationPlayer / NetworkBehaviour, and a NetworkManager node that spawns/despawns networked scenes and drives interpolation. The engine-agnostic replication (SetNet.StateSync) is unchanged; this is the Godot binding. Depends on SetNet.StateSync + SetNet.Godot + GodotSharp. |
|
|
SetNet.StateSync.LagCompensation
Server-side lag compensation for SetNet.StateSync: record a short history of entity positions each tick and rewind the world to a past moment for fair hit detection. Depends on SetNet + SetNet.StateSync. |
|
|
SetNet.StateSync.Prediction
Client-side prediction/reconciliation for SetNet.StateSync: buffer applied inputs and, on a corrective snapshot, discard acknowledged inputs and replay the rest on top of the authoritative state (rewind and replay). Depends on SetNet + SetNet.StateSync. |
GitHub repositories
This package is not used by any popular GitHub repositories.