Post

EOS-Native: I Built a Standalone Multiplayer Framework for Unity

What started as a FishNet transport turned into a full multiplayer networking framework. 80 managers, 46K lines, zero middleware.

EOS-Native: I Built a Standalone Multiplayer Framework for Unity

EOS-Native

Five days ago I released FishNet-EOS-Native; a transport layer for FishNet that talks directly to the EOS SDK. Cool, works great, shipped it.

Then I kept going.

What Happened

I was building features on top of FishNet (host migration, SyncVars, replays) and kept running into the same problem: FishNet’s architecture fights you on P2P. RPCs route through the host. Migration destroys and recreates objects. SyncVars use reflection hacks to survive migration.

So I stopped writing a transport and started writing a framework.

EOS-Native is a complete multiplayer networking stack for Unity built directly on top of EOS P2P. No FishNet, no Mirror, no Photon, no middleware. Just EOS packets and a 4-layer architecture I own top to bottom.

The Architecture

1
2
3
4
Layer 3: Game Systems     (planned: prediction, rollback, spatial interest)
Layer 2: High-Level Net   (NetworkObject, SyncVar, NetworkTransform, EasySync)
Layer 1: Transport Toolkit (NetWriter/Reader, MessageRouter, PacketFragmenter)
Layer 0: Raw EOS SDK      (P/Invoke bindings, native libs for 7 platforms)

Layer 0 is the official EOS C# SDK with native binaries for Windows (x86/x64), macOS, Linux (x64/ARM64), iOS, and Android.

Layer 1 handles binary serialization with pooling, packet fragmentation for EOS’s 1170-byte limit, typed message routing, and frame-level batching.

Layer 2 is where it gets interesting. NetworkObject, SyncVar<T>, SyncList<T>, SyncDictionary, NetworkTransform with spring physics and 3-tier LOD, NetworkAnimator, and EasySync (Normcore-style no-code property sync from the Inspector).

Layer 3 is the roadmap; prediction, rollback, spatial interest management.

Why P2P Mesh Matters

In FishNet/Mirror, all RPCs go through the host. Player A wants to tell Player B something? A -> Host -> B. The host is a bottleneck.

In EOS-Native, RPCs go direct. A -> B. The host only matters for authority arbitration and late-join snapshots. This means less latency for player-to-player communication and less load on the host.

Zero-Hitch Host Migration

This is the feature I’m most proud of. When the host disconnects in FishNet, every NetworkObject gets destroyed and recreated on the new host. That means a frame of flicker, lost particle effects, reset animations, and reflection hacks to save/restore SyncVars.

In EOS-Native, nothing gets destroyed. The authority pointer changes, the RPC migration buffer flushes queued messages, and the game continues. The EOS lobby layer (voice, chat, presence) survives migration automatically since it’s a separate layer from the networking.

80 Managers

The framework ships with 80 C# manager classes covering:

  • Lobbies - create/search/join, 4-digit codes, quick match, fluent builder API
  • Voice - RTC voice chat, audio device selection, pitch shifting
  • Chat - lobby text chat, global channel-based chat
  • Social - friends, party system, presence, Discord rich presence
  • Ranked - ELO/Glicko-2/SimpleMMR matchmaking with seasons
  • Stats - leaderboards, achievements, match history
  • Replays - record/playback with timeline, auto-detected highlights (multi-kill, clutch, comeback), voice recording
  • Moderation - reports, sanctions, vote kick, AFK detection
  • Storage - cloud saves (400MB per player, 10GB title)
  • Anti-cheat - EOS EAC integration
  • UI - F1 debug overlay (6 tabs), Canvas UI for mobile, runtime console

All of this is free. No per-CCU fees, no middleware licenses. EOS is free; this package is free.

The Hard Parts (Round 2)

Binary serialization - wrote NetWriter/NetReader from scratch with pooling. Every SyncVar dirty-tracks its own state and serializes only when changed. Sequence numbers on every packet so stale data gets rejected.

NetworkTransform - this one took a while. It’s a hybrid system: spring physics for smooth local interpolation, buffered interpolation for remote peers, extrapolation with velocity prediction when packets are late, and a 3-tier LOD system (Full/Tweened/Simple) based on distance with hysteresis to prevent thrashing.

Late-join snapshots - when a new peer joins, the host sends a full state dump of every NetworkObject, their SyncVars, ownership, and spawn data. The new peer reconstructs the entire game state from this snapshot.

Install

UPM git URL:

1
https://github.com/TrentSterling/EOS-Native.git?path=Assets/com.tront.eos-native

Or just copy Assets/com.tront.eos-native/ into your project’s Packages/ folder.

Add EOS_DISABLE to your scripting defines if you need to strip EOS from compilation.

What’s Next

  • Packet compression (LZ4 or similar)
  • Client-side prediction and rollback
  • Spatial interest management
  • SyncVar LOD tiers (dynamic sync rate for all SyncVars, not just transforms)
  • Multi-transport crossplay (EOS + Steam side by side)
  • Spectator mode
  • Dedicated server support

The FishNet transport (FishNet-EOS-Native) still exists and still works. It depends on this package for the EOS SDK and lobby/voice/social managers. But if you’re starting fresh and don’t need FishNet’s abstractions, EOS-Native gives you the full stack with less overhead.

Docs are here - 51 pages covering setup, architecture, every feature, and API reference.