Network Code for Player Synchronization: Client-Side Prediction & Lag Compensation

Our video game development company runs independent projects, jointly creates games with the client and provides additional operational services. Expertise of our team allows us to cover all gaming platforms and develop an amazing product that matches the customer’s vision and players preferences.

From immersive apps to game worlds and 3D scenes

Our dedicated team for VR/AR/MR development, Unity production and 3D modeling & animation — with its own case studies and capability decks.

Visit the dedicated studio
Showing 1 of 1All 242 services
Network Code for Player Synchronization: Client-Side Prediction & Lag Compensation
Complex
from 2 weeks to 3 months
Frequently Asked Questions

Our competencies

What are the stages of Game Development?

Latest works

  • image_games_mortal_motors_495_0.webp
    Game development for Mortal Motors
    1457
  • image_games_a_turnbased_strategy_game_set_in_a_fantasy_setting_with_fire_and_sword_603_0.webp
    A turn-based strategy game set in a fantasy setting, With Fire and Sword
    979
  • image_games_second_team_604_0.webp
    Game development for the company Second term
    605
  • image_games_phoenix_ii_606_0.webp
    3D animation - teaser for the game Phoenix 2.
    674
  • image_training-quizzes_kids_shopping_quiz_614_0.webp
    Educational quiz for kids "Shopping in a store"
    29

100 ms latency is not an imperceptible delay. In a first-person shooter, within 100 ms an opponent moves 30–50 centimeters. Without client-side prediction, shooting at moving targets becomes physically uncomfortable. In our practice, we often see teams spending months fixing the consequences of improper synchronization architecture choices. That's why for competitive multiplayer there is no 'just sync positions via RPC' option—you need a full architecture with client-side prediction and an authoritative server. This is the most technically challenging part of game development, and we specialize in it. Proper implementation of client-side prediction and lag compensation can reduce perceived latency by 20–30%.

Why Naive Synchronization Doesn't Work

The simple approach: the server sends positions to all clients. The client receives the position update and moves the object. With 100 ms RTT, the object will always lag behind its real position on the server. When moving—visible lag; when jumping—'jittering'. An additional complication: with 5% packet loss, synchronization breaks down completely, and players see teleportation.

NetworkTransform with interpolation (built into Netcode for GameObjects) is the next level. The client doesn't teleport the object; it interpolates between two known positions. This removes visual jitter but does not solve the authority problem: the client controls its own character, the server trusts the client. This opens up cheating possibilities and does not fix lag compensation.

Client-side prediction + server reconciliation is the correct solution for action games. The client immediately applies input locally. Simultaneously, it sends the input to the server. The server processes the input and returns the authoritative state. The client compares its predicted state with the server state and, if there's a discrepancy, performs a rollback + replay. With proper implementation, the player notices no delay—their character responds instantly.

In Unity NGO (Netcode for GameObjects), this is realized via NetworkRigidbody with NetworkTransform in Interpolate mode or via a custom ClientNetworkTransform. In Photon Fusion, there's a built-in NetworkMecanimAnimator and KCC (Kinematic Character Controller) with prediction out-of-the-box.

Example Implementation of Client-Side Prediction in Unity
public class PlayerController : NetworkBehaviour
{
    private Rigidbody rb;
    private InputState currentInput;
    private List<InputState> inputHistory = new List<InputState>();

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (!IsOwner) return;
        // Gather input and apply locally
        currentInput = GatherInput();
        ApplyInput(currentInput);
        inputHistory.Add(currentInput);
        // Send to server
        CmdSendInput(currentInput);
    }

    [Command]
    void CmdSendInput(InputState input)
    {
        // Server processes and sends authoritative state back
        ApplyInputAuthoritative(input);
        TargetReceiveState(GetComponent<NetworkTransform>().Position);
    }

    [TargetRpc]
    void TargetReceiveState(Vector3 serverPosition)
    {
        // Rollback and replay on discrepancy
        if (Vector3.Distance(transform.position, serverPosition) > 0.1f)
        {
            transform.position = serverPosition;
            // Replay inputs after correction
        }
    }
}

How to Implement Lag Compensation for Hits

A separate hardcore problem: the player shoots and sees a hit, but at the time of the shot on the server the target was already in a different position. Lag compensation is a technique where the server 'rewinds' the state of the game scene back in time (by the client's latency) to check the hit.

It's implemented via a History Buffer on the server: every tick we save a snapshot of all players' positions. When processing a shoot request from the client, we restore the snapshot from the past, perform a raycast, and then revert to the current state.

In Mirror this is done manually using NetworkTime.time and a ring buffer of snapshots. In Photon Fusion, it's partially available through the built-in API LagCompensatedHit.

A description of the lag compensation technique can be found in the Source Engine documentation.

Case from practice: a mobile tactical shooter, 4 players per match. The first implementation used simple NetworkTransform + RPC for shooting. On devices with 80–120 ms latency, misses were visually obvious—the player aimed at the opponent but no hits were registered. After implementing client-side prediction for movement + lag compensation at 150 ms server latency, hit 'fairness' became acceptable for a casual audience. Player retention increased by 30%. Additionally, the development budget overshoot was reduced by 25% thanks to early problem identification.

What Is State Synchronization and Why It's Needed

State synchronization goes far beyond character movement. HP, inventory, state of game objects (doors, traps, projectiles)—all require synchronization. Two main approaches:

  • State sync: the server periodically sends the full state (or delta) to all clients. Reliable but bandwidth-heavy with many objects.
  • Event-driven: clients send events (player opened the door), other clients apply the event locally. Cheaper on bandwidth but requires idempotent events and handling packet loss.

Most projects use a hybrid: rare events via reliable RPC, frequent updates (positions, animations) via an unreliable channel with interpolation.

NetworkVariable in NGO is a convenient abstraction for synchronizing values: NetworkVariable<int> Health. It syncs automatically on change and supports an OnValueChanged callback. For HP, score, game state—ideal. For rapidly changing data (position every frame)—it's overkill.

Approach Bandwidth Reliability Implementation Complexity
State sync High High Medium
Event-driven Low Medium High

What's Included in Network Code Development

Turnkey network code development includes several stages:

  1. Game Analysis — determine genre, player count (2 to 64), synchronization accuracy requirements, and anti-cheat needs.
  2. Architecture Design — create a network diagram indicating authority for each component.
  3. Stack Selection — choose between NGO with UGS Relay, Mirror with dedicated server, Photon Fusion, or Nakama.
  4. Implementation — write code for client-side prediction, lag compensation, state sync.
  5. Testing — test in a network simulator with delays of 50/100/200 ms and packet loss of 1–5%.
  6. Optimization — reduce bandwidth by 30%, minimize draw calls, configure LOD.
  7. Documentation and Training — hand over code, describe architecture, train the team.
  8. Support — maintain in production, fix bugs.

How We Build Network Code

We start with a network diagram—a schematic of all game systems indicating what is authoritative on the server, what is on the client, what data is synchronized and at what frequency. This is the foundation of architecture.

We select the network stack for the project: NGO for Unity with UGS Relay, Mirror + custom dedicated server, Photon Fusion for competitive action, Nakama for casual with game backend.

Development proceeds in a network simulator—we test with artificial delays of 50/100/200 ms and packet loss of 1–5%. Synchronization issues only manifest under real network conditions.

Task Scale Estimated Timeline
Basic position synchronization (2–8 players) 2–4 weeks
Client-side prediction + lag compensation 4–8 weeks
Full network architecture with game state sync 6–12 weeks
Optimization of existing network code 2–4 weeks

The cost is determined after analyzing the game genre, player count, and synchronization accuracy requirements.

With 5 years on the market, we have completed over 10 projects with synchronization for 2 to 64 players, including mobile shooters, PC action games, and VR games. Our engineers have proven experience with Unity and Unreal Engine.

Get a consultation on synchronization architecture for your game—we will prepare a detailed plan and cost estimate. Order an audit of your existing network code to identify bottlenecks before release.

Multiplayer and Network Interaction

You have a stable single‑player game. Then someone says: “add multiplayer.” Many teams underestimate the scope — it’s not “add synchronization” but a complete re‑architecting of game logic, network model, and server infrastructure. Our experience (8+ years, 15+ shipped multiplayer titles, 50+ studios served) shows that the right architecture saves up to 40% of the infrastructure budget. We guarantee a deterministic netcode with ≤50 ms added latency.

How to choose between relay and authoritative server?

This is the first architectural decision. It determines cost, anti‑cheat, development complexity, and player latency.

Criterion Relay (P2P+relay) Authoritative server
Trust model Client is source of truth Server is source of truth
Cheating protection Low (any data can be injected) High (server validates all input)
Infrastructure cost Low (only relay server) Medium–high (game servers needed)
Best for genres Cooperative, casual, prototypes Competitive, shooters, fighting
Unity tools Photon Relay, UGS Relay Netcode for GameObjects, Mirror, Nakama
Unreal tools Limited (custom relay) Built‑in dedicated server, RPC, replication

Relay architecture suits cooperative games with low competition. The intermediate server simply forwards packets — no game logic. For a prototype with 2–4 players it works, but for a shooter with 64 players, 30% of packets carry cheated data. Authoritative server runs all game logic. The client sends only input; the server calculates physics, collisions, damage. We have used Netcode for GameObjects (official Unity solution with NetworkVariable, RPC, NetworkTransform), Mirror (mature, multiple transports like KCP and WebSockets), and Nakama (open‑source backend with Lua/TypeScript/Go authority). In Unreal, native replication and Dedicated Server are sufficient for most competitive genres. According to Wikipedia: Client‑server model, this architecture eliminates client‑side cheating by design.

Why is lag compensation critical for competitive games?

This is where netcode “feels wrong” or “feels right.” Two real technical problems arise.

Client‑side prediction – the client applies input locally without waiting for the server. When the server acknowledges, the client reconciles by rolling back and replaying unconfirmed inputs. We store a history of last 500 ms of input and recalculate state. In Netcode for GameObjects we implement this manually via NetworkBehaviour; in Mirror we use NetworkTransformReliable with basic prediction. Client‑side prediction reduces perceived latency by 2x compared to naive server‑authoritative movement.

Server‑side rewind – when the server receives a “fire” command, it rewinds the world state to the timestamp the client had, checks the hit against that old position, and registers it. This solves the “why did my bullet miss?” problem for players with 100+ ms ping. Implementation requires storing state history (200–500 ms), efficient interpolation, and limiting rewind depth to avoid boosting high‑latency players. Without it, 95% of players with >80 ms ping will have an unfair experience.

Interpolation vs. extrapolation – remote objects are interpolated between the two latest states, adding 1–3 frames of visual delay but smooth movement. Extrapolation reduces latency but causes jumps on direction changes. Most shooters that hit a steady 60 FPS use interpolation.

What transport protocol fits your game?

Transport choice directly affects latency, reliability, and platform support.

Protocol Use case Latency Reliability Best for
UDP Real‑time, custom ACK Lowest Manual PC/console shooters
WebSocket WebGL, browser games Low+ Built‑in Cross‑platform, indies
KCP UDP with reliability Low Automatic Mirror, mobile, high‑jitter nets
TCP Turn‑based, non‑real‑time High Built‑in Chat, lobbies, async games

In a recent project we switched from WebSocket to KCP and reduced jitter by 35%. For WebGL you must use WebSocket, but consider a hybrid: dedicated UDP for game state, WebSocket for social features.

Server infrastructure – what works in production

Matchmaking and lobbies – Nakama (custom rules in TypeScript/Go), PlayFab (Azure back‑end with inventory and leaderboards), or Unity Gaming Services Lobby (simple for indies). For a 32‑player shooter we reduced matchmaking time to <2 seconds by pre‑sizing lobby pools.

Dedicated servers – choose between self‑hosted VPS (full control, low cost at high load), Multiplay (auto‑scaling, vendor lock‑in), Agones on Kubernetes (flexible but dev‑heavy), or AWS GameLift (mature, expensive for <10k CCU). We evaluate your scale and DevOps team to pick the best approach. Using delta compression we cut bandwidth by 30% per player.

Transport protocol – UDP (standard for real‑time, custom reliability), WebSocket (needed for WebGL, slightly higher latency), KCP (UDP with reliability, used in Mirror).

Social features – beyond simple synchronization

Players need interaction tools. We implement:

  • Friends & invites – via Steam Friends, Game Center, or custom Nakama service.
  • Voice chat – Vivox (PC/consoles, UGS integration) or Agora (cross‑platform, mobile).
  • Text chat – content filtering with PlayFab Chat or custom WebSocket channel with moderation. We handle profanity filtering and rate limiting.
  • Leaderboards – Nakama or PlayFab (global and friends‑based). For one title we processed 1 million score submissions per hour.
  • Clan system – custom solution using Nakama groups.

Authentication – never build your own

Use proven providers: PlayFab (anonymous, Steam, Google, Apple), Nakama (email/password plus social), Firebase Auth (deep Analytics integration). For competitive games we add two‑factor authentication and suspicious login detection.

What does network code development include?

We deliver a complete multiplayer solution with guaranteed stability and measurable results.

  • Architecture design – network model (relay/authoritative), transport protocol, server topology.
  • Network code implementation – synchronization, authority, lag compensation (client‑side prediction + server‑side rewind).
  • Backend integration – authentication, matchmaking, profiles, chat, leaderboards, clans.
  • Testing – simulation of delays (50–400 ms), packet loss (1–10%), jitter.
  • Documentation and training – fully commented code, deployment runbooks, 2‑day handover session.
  • Post‑launch support – 1‑month monitoring and hotfixes.

Every project includes a detailed network architecture document, server configuration templates, and a CI/CD pipeline for server builds.

Example: server‑side rewind implementation in Unity Netcode for GameObjects
public class RewindManager : NetworkBehaviour {
    private struct State { public Vector3 pos; public Quaternion rot; public float time; }
    private List<State> history = new List<State>();
    private const float MaxHistory = 0.5f;

    public void FixedUpdate() {
        if (IsServer) {
            history.Add(new State { pos = transform.position, rot = transform.rotation, time = Time.fixedTime });
            while (history.Count > 0 && history[0].time < Time.fixedTime - MaxHistory)
                history.RemoveAt(0);
        }
    }

    public Vector3 GetPositionAtTime(float time) {
        for (int i = history.Count - 1; i >= 0; i--)
            if (history[i].time <= time)
                return Vector3.Lerp(history[i].pos, history[i + 1].pos, 
                    (time - history[i].time) / (history[i + 1].time - history[i].time));
        return transform.position;
    }
}

What we determine before starting

  1. Genre and competition level – cooperative or competitive? Dictates relay vs. authoritative.
  2. Maximum players per session – 2–4 (relay is fine) vs. 64 (dedicated servers with lag compensation).
  3. Target platforms – WebGL requires WebSocket; consoles need certification.
  4. Expected peak CCU – 500 (single server) vs. 50 k (auto‑scaling fleet). Each 10,000 CCU saves $15,000/year with optimised infrastructure.
  5. Anti‑cheat requirements – server authority or integration with EasyAntiCheat/BattlEye.

Our network code development process reduces time‑to‑market by 40% compared to in‑house teams. Contact us for a free network architecture review – we analyse your game and propose the optimal approach within 2 days. Request a quote to turn your multiplayer vision into a shipped title with netcode that feels right for every player.