Multiplayer Game Networking: Architecture & Implementation
Multiplayer networking turns a single-player game into a shared experience. Players across the world see each other, interact in real time, and compete or cooperate — all while dealing with latency, packet loss, and bandwidth limits.
In this tutorial, you’ll learn networking architectures (client-server vs peer-to-peer), authoritative server design, lag compensation techniques (client-side prediction, server reconciliation, interpolation), transport protocols (WebSocket, UDP, TCP), and implementations using Photon, Mirror, and Unity Netcode for GameObjects.
What You’ll Learn
- Client-server vs peer-to-peer architecture tradeoffs
- Authoritative server design against cheating
- Client-side prediction for responsive controls
- Server reconciliation to correct drift
- Entity interpolation for smooth remote movement
- UDP vs TCP for real-time games
- Photon, Mirror, and Unity Netcode for GameObjects
Why Multiplayer Matters
Multiplayer games generate billions in annual revenue. From Fortnite to Among Us, network code determines whether a game feels responsive or laggy. At DodaTech, real-time communication techniques power collaborative features in Doda Browser and DodaZIP.
Learning Path
flowchart LR
A[2D Animation] --> B[Multiplayer Networking<br/>You are here]
B --> C[Game Optimization]
B --> D[Game Audio]
style B fill:#f90,color:#fff
Client-Server vs Peer-to-Peer
| Aspect | Client-Server | Peer-to-Peer (P2P) |
|---|---|---|
| Authority | Server is truth | Each peer decides |
| Cheating | Hard (server validates) | Easy (clients trust each other) |
| Latency | Through server (higher) | Direct connections (lower) |
| Scaling | Server bandwidth bottleneck | Bandwidth distributed |
| Examples | Fortnite, Valorant, Call of Duty | Fighting games, LAN parties |
Start with client-server. It’s harder to cheat and easier to debug.
Authoritative Server
The server is the final authority on game state. Clients send inputs, not positions:
Client Frame 123: "I pressed W and Jump"
Server Frame 123: "Your position is now (12.5, 0, 8.3), velocity (5, 7, 0)"This prevents speed hacks and teleport cheats. The server never trusts the client.
// Unity Netcode — authoritative player movement
using Unity.Netcode;
using UnityEngine;
public class NetworkedPlayer : NetworkBehaviour
{
public float speed = 5f;
void Update()
{
if (!IsOwner) return; // Only control our own player
float moveX = Input.GetAxis("Horizontal");
float moveZ = Input.GetAxis("Vertical");
Vector3 move = new Vector3(moveX, 0, moveZ) * speed * Time.deltaTime;
// Send input to server via ServerRpc
if (move != Vector3.zero)
MoveServerRpc(transform.position + move);
}
[ServerRpc]
void MoveServerRpc(Vector3 newPosition)
{
// Server validates and moves
transform.position = newPosition;
}
}Expected behavior: Only the owning client reads input. The input is sent to the server via ServerRpc. The server applies it. Other clients see the server-confirmed position.
Client-Side Prediction
Without prediction, the player feels input lag equal to their ping. Prediction solves this:
// Client predicts movement locally, sends input to server
void Update()
{
if (!IsOwner) return;
// Read input
Vector2 input = new Vector2(
Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")
);
// Predict locally immediately
Vector3 predictedPosition = rb.position +
new Vector3(input.x, 0, input.y) * speed * Time.fixedDeltaTime;
rb.MovePosition(predictedPosition);
// Send input to server with sequence number
MoveServerRpc(input, currentSequenceNumber++);
}Server reconciliation corrects the client when the server disagrees:
Client predicted: (12.5, 0, 8.3) at sequence 123
Server confirmed: (12.4, 0, 8.2) at sequence 123
Client corrects: Lerp from predicted to server positionEntity Interpolation
To see other players move smoothly, render their position from 50ms ago:
public class RemotePlayerInterpolation : MonoBehaviour
{
private Queue<(Vector3 pos, float time)> positions = new();
void Update()
{
while (positions.Count > 2 &&
positions.Peek().time < NetworkTime.Time - 0.05f)
{
positions.Dequeue();
}
if (positions.Count >= 2)
{
var from = positions.Dequeue();
var to = positions.Peek();
float t = (NetworkTime.Time - 0.05f - from.time) /
(to.time - from.time);
transform.position = Vector3.Lerp(from.pos, to.pos, t);
}
}
}Expected behavior: Remote players move smoothly rather than teleporting between position updates.
UDP vs TCP for Games
| Protocol | Use For | Why |
|---|---|---|
| TCP | Chat, inventory, login | Reliable, ordered delivery |
| UDP | Position, velocity, shooting | Fast, no retransmission delay |
TCP retransmits lost packets, causing head-of-line blocking — a lost packet delays all subsequent data. UDP is “fire and forget,” better for real-time updates where fresh data is more valuable than old data retransmitted.
// Using Unity Transport (UDP-based)
using Unity.Netcode;
using Unity.Networking.Transport;
void Start()
{
NetworkManager.Singleton.NetworkConfig.NetworkTransport =
GetComponent<UnityTransport>();
}Networking Libraries Comparison
| Library | Transport | Cost | Best For |
|---|---|---|---|
| Netcode for GameObjects | Unity Transport (UDP) | Free | Unity games, official support |
| Mirror | TCP/UDP (LLAPI) | Free | High-level API, community |
| Photon PUN | Photon Cloud (UDP) | Free tier / paid | Quick setup, cloud hosting |
| Photon Fusion | Photon Cloud (UDP) | Paid | State synchronization, lag comp |
Common Mistakes
1. Trusting Client Positions
Never accept transform.position from clients. Accept inputs only. Otherwise, hackers teleport across the map.
2. No Client-Side Prediction
Without prediction, the game feels sluggish for everyone. Always predict locally and reconcile.
3. Broadcasting Full State Every Frame
Send deltas (what changed) not full snapshots. Use interest management — don’t send updates for objects far from the player.
4. Only Testing on Localhost
Localhost testing hides all latency issues. Use Unity’s Network Simulator or Clumsy to test with 100-300ms latency and 5% packet loss.
5. Using TCP for Real-Time Data
TCP lost-packet retransmission causes delays. Use UDP for position updates. Reserve TCP for reliable data (chat, inventory).
6. Missing Network Spawning
Instantiating with new GameObject() won’t replicate. Always use NetworkObject.Spawn().
7. Not Using Interest Management
Without it, every client receives updates for every object. Implement area-of-interest to reduce bandwidth.
Practice Questions
1. Why is client-server more cheat-resistant than P2P?
The server validates all actions. Clients can’t modify game state because they only send inputs.
2. What problem does client-side prediction solve?
Input lag. The client moves immediately instead of waiting for the server round-trip.
3. What does the [ServerRpc] attribute do?
Marks a method that runs on the server but is called from the client. The Unity Netcode framework handles serialization and transport.
4. Why use interpolation for remote players?
Without interpolation, remote players appear to teleport between positions. Interpolation smooths the movement.
5. Challenge: Implement a simple chat system.
Use NetworkManager and [ClientRpc] to broadcast messages. Send the player name + message string. Display in a UI ScrollView.
Mini Project: Two-Player Movement
Build a networked scene:
- Create a Player prefab with NetworkObject + NetworkBehaviour
- Implement player movement (only for IsOwner)
- Use NetworkManager.Singleton.StartHost() on one instance
- Use StartClient() on the second instance
- Both players see each other moving with interpolation
FAQ
What’s Next
Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro