Performance
GONet is designed for hundreds of concurrent networked objects with minimal overhead — the included RPC Playground scene runs 800+ networked objects simultaneously. Key systems include SoA blending (6-9x CPU reduction), quantization (50% bandwidth savings), and velocity-augmented sync (90%+ bandwidth reduction). This page covers how to get the most out of each system.
Use UpdateAfterGONetReady() Instead of Update()
Unity's built-in Update() callback registers a separate invocation for every MonoBehaviour that defines it. With many networked objects, this overhead adds up. GONet provides a more efficient alternative.
// RECOMMENDED: Single internal loop, zero overhead if not overridden
internal override void UpdateAfterGONetReady()
{
if (IsMine)
{
// Your game logic here
}
}
// AVOID: Per-object Unity callback overhead
// void Update() { } -- each object registers a separate callbackWhy it is faster: With N networked objects, GONet makes 1 internal loop call that iterates all participants, instead of N separate Unity Update() callbacks. The same applies to FixedUpdateAfterGONetReady() and LateUpdateAfterGONetReady().
Quantize Position and Rotation
Quantization reduces the number of bits sent per value by mapping a floating-point range to a fixed number of integer steps. For most games, the precision loss is imperceptible.
- •16-bit quantization -- Approximately 0.015 meter precision over a [-500, 500] range. This gives 50% bandwidth savings compared to full 32-bit floats. Suitable for positions and rotations.
- •8-bit quantization -- 75% bandwidth savings. Ideal for less-critical values like health bars, cooldown timers, or UI indicators where coarser precision is acceptable.
Bandwidth comparison: A standard position update with 3 floats costs 12 bytes (96 bits). With 16-bit quantization, the same position costs 6 bytes (48 bits) -- a 50% reduction per update.
Enable Velocity-Augmented Sync
For objects with predictable motion -- characters, vehicles, projectiles -- velocity-augmented sync can reduce bandwidth by 90% or more. Instead of sending full position values every frame, GONet alternates between position VALUE packets and VELOCITY packets. Clients extrapolate between updates using the last-known velocity.
- •Slow-moving objects see the highest savings (90%+ bandwidth reduction) because velocity changes infrequently.
- •Enable it by setting IsVelocityEligible = true on the [GONetAutoMagicalSync] attribute.
- •Best suited for objects whose movement is continuous and relatively predictable. Erratic, teleporting objects will not benefit as much.
SoA Blending System
GONet uses a Structure-of-Arrays (SoA) layout for blending incoming network values. This design enables Unity Burst-compiled parallel jobs to process all networked objects in a single pass, resulting in up to 85% CPU reduction compared to per-object blending — tested with 800+ objects in the included RPC Playground scene.
- •Hermite spline interpolation -- Uses cubic Hermite splines for smooth curve fitting between network samples, producing visually smoother motion than linear interpolation.
- •Lock-free ring buffers -- Incoming network values are stored in lock-free ring buffers, avoiding contention between the networking thread and the main thread.
- •SIMD optimization -- Unity Jobs + Burst compilation enables SIMD vector operations for batch processing of float arrays.
- •Fully automatic -- no configuration needed. The SoA blending system works behind the scenes for all synced values.
Adaptive Congestion Management
GONet automatically adjusts its blend buffer based on actual network update rates, preventing visual stutter during periods of network pressure.
- •Normal conditions (24Hz): buffer approximately 100ms
- •Under congestion (2Hz): buffer auto-expands to approximately 750ms
You can configure the adaptive buffer in GONetGlobal using these settings:
- enableAdaptiveBlendingBuffer -- toggle the system on or off
- adaptiveBufferMinLeadTimeMs -- minimum buffer duration in milliseconds
- adaptiveBufferMaxLeadTimeMs -- maximum buffer duration in milliseconds
Time Sync Performance
GONet's time synchronization system is designed for minimal overhead:
- •Nanosecond-resolution reads -- Time reads use high-resolution timers, avoiding the overhead of DateTime.Now or Time.realtimeSinceStartup.
- •Dedicated channel -- Time sync runs on a high-priority system channel, separate from gameplay traffic. It is never delayed by large state updates.
- •Golden Sample filtering -- Only the most reliable time samples are applied, preventing clock instability from network jitter or bufferbloat.
Message Compression
GONet uses a multi-layer compression strategy:
- •Custom bit-packing -- Sync values are packed at the bit level based on their quantization settings, eliminating wasted bytes from standard data types.
- •LZ4 compression -- Every packet GONet sends is automatically LZ4 compressed, regardless of transport. Packets under 100 bytes are passed through uncompressed to avoid overhead on tiny messages.
- •MemoryPack serialization -- Events and RPCs use MemoryPack for fast, compact serialization.
- •Message bundling -- Multiple messages destined for the same client are bundled into a single packet to reduce per-packet overhead.
Congestion Management
GONet includes adaptive per-client congestion control that prevents network saturation without sacrificing visual quality:
- •Temporal thinning -- Under congestion, GONet reduces the sync rate for less-critical values while maintaining full rate for important ones.
- •Frame spreading -- Instead of sending all updates in a single burst, updates are spread across multiple frames to smooth out network traffic.
- •Per-client backpressure -- Each client connection is managed independently. A slow client does not affect the sync rate for other clients.
Object PoolingGONet Legendary
Frequently spawned and despawned objects -- projectiles, particle effects, pickup items -- should use object pooling. Pooling reuses deactivated instances instead of allocating new ones, preventing allocation spikes and garbage collection pauses.
- •GONet includes an adaptive pool scaler that automatically grows the pool under demand, so you do not need to pre-allocate a fixed number of objects.
- •Pooled objects implement IGONetPoolResettable to reset their state when borrowed from or returned to the pool.
Monitoring
GONet provides diagnostic flags and monitoring utilities to help you identify performance bottlenecks during development.
// Enable debug logging
GONetMain.EnableDetailedReliableTransportLogging = true;
GONetMain.EnableSceneLoadCompleteTracing = true;
// Monitor pools
var monitor = GONetMain.GetMonitor();Keep detailed logging disabled in production builds -- it adds overhead. Use it during development to trace reliable transport behavior and scene load sequencing.
Bandwidth Cheat Sheet
Quick reference for the bandwidth cost of different sync strategies:
| Strategy | Bits per Value | Savings |
|---|---|---|
| Unquantized float | 32 | -- |
| 16-bit quantized | 16 | 50% |
| 8-bit quantized | 8 | 75% |
| Velocity-augmented | ~3 avg | 90%+ |
| Position (3 axes) | Bits per Update | Savings |
|---|---|---|
| Unquantized (3 floats) | 96 | -- |
| 16-bit quantized (3 axes) | 48 | 50% |
| Velocity-augmented | ~10 avg | 90%+ |
Best Practices Summary
- •Use UpdateAfterGONetReady() instead of Update()
- •Quantize positions (16 bits), rotations (16 bits), and health/small values (8 bits)
- •Enable velocity sync for objects with predictable motion
- •Pool projectiles, particle effects, and other frequently spawned objects
- •Use sync profiles for consistency across your project
- •Disable components, not GameObjects -- deactivating a GameObject has broader side effects than disabling individual components
- •Keep RPC parameter count at 8 or below. If you need more, pack them into a struct and pass that instead
Next Steps
For a complete reference of all the classes and configuration options mentioned on this page:
- →API Reference -- Quick reference for all major classes, attributes, configuration options, and constants.