Skip to main content

Command Palette

Search for a command to run...

Step-by-Step: Your First Netcode Implementation in Unity

Updated
7 min readView as Markdown

Adding multiplayer to a Unity project can feel complex at first, but the core networking flow becomes much easier once you build a small working example.

In this Unity netcode tutorial, we’ll create a simple host-and-client setup using Netcode for GameObjects, spawn networked players, synchronize movement, and test the result locally.

Understanding these fundamentals is also an important part of modern Unity game development, especially when building real-time multiplayer experiences.

Our basic architecture will look like this:

Player 1
   ↓
Host
   ↓
NetworkManager
   ↓
Unity Transport
   ↓
Client
   ↓
Player 2

Step 1: Install Netcode for GameObjects

Create a Unity project and open:

Window → Package Management → Package Manager

Install:

Netcode for GameObjects

You’ll also use Unity Transport for the underlying network communication.

The basic stack is:

Netcode for GameObjects
        +
Unity Transport

For a first implementation, this gives you everything needed to create a local client-server multiplayer session.


Step 2: Add the NetworkManager

Create an empty GameObject named:

NetworkManager

Add these components:

  • NetworkManager

  • UnityTransport

The NetworkManager is responsible for managing the multiplayer session.

It handles tasks such as:

Starting the host
Connecting clients
Spawning players
Network configuration
Managing network prefabs

For this tutorial, we’ll use a standard client-server setup.


Step 3: Create Host and Client Buttons

Create a simple Canvas with two buttons:

Start Host
Start Client

Then add this script:

using Unity.Netcode;
using UnityEngine;

public class NetworkLauncher : MonoBehaviour
{
    public void StartHost()
    {
        NetworkManager.Singleton.StartHost();
    }

    public void StartClient()
    {
        NetworkManager.Singleton.StartClient();
    }
}

Connect each button to its matching method.

The flow becomes:

Start Host
   ↓
Server + Local Client

Start Client
   ↓
Connect to Host

The host acts as both the server and a participating client.


Step 4: Create a Networked Player

Create a simple player using a Cube, Capsule, or character model.

Add:

NetworkObject
NetworkTransform
NetworkPlayer script

Then convert the object into a prefab.

Your hierarchy might look like:

Player
├── NetworkObject
├── NetworkTransform
└── NetworkPlayer

The NetworkObject gives Netcode a way to identify and manage the object across connected clients.


Step 5: Assign the Player Prefab

Select your NetworkManager.

Find the:

Player Prefab

field and assign your networked Player prefab.

Now, whenever a client joins successfully, Netcode can create a player object automatically.

Instead of manually placing multiple players into the scene, the networking system handles player creation for you.


Step 6: Add Basic Player Movement

Create a script named:

NetworkPlayer.cs

Example:

using Unity.Netcode;
using UnityEngine;

public class NetworkPlayer : NetworkBehaviour
{
    [SerializeField]
    private float speed = 4f;

    private void Update()
    {
        if (!IsOwner)
            return;

        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");

        Vector2 input = new Vector2(horizontal, vertical);

        if (input.sqrMagnitude > 0)
        {
            MoveRpc(input.normalized);
        }
    }

    [Rpc(SendTo.Server)]
    private void MoveRpc(Vector2 input)
    {
        Vector3 movement = new Vector3(
            input.x,
            0,
            input.y
        );

        transform.position +=
            movement * speed * Time.deltaTime;
    }
}

The important check is:

if (!IsOwner)
    return;

This ensures that each client controls only its own player.

Conceptually:

Client 1 → Player 1
Client 2 → Player 2

Without ownership checks, one client could unintentionally control other players.


Step 7: Understand the RPC

This method:

[Rpc(SendTo.Server)]
private void MoveRpc(Vector2 input)

is an RPC, or Remote Procedure Call.

The flow is:

Client Input
    ↓
RPC
    ↓
Server
    ↓
Server Updates Player

The client sends its movement request to the server, and the server applies the movement.

For a beginner project, this is a useful way to understand client-server communication.

For larger competitive games, this foundation usually grows into a more complete server-authoritative multiplayer architecture involving dedicated servers, matchmaking, prediction, validation, and latency management.


Step 8: Synchronize Player Movement

The server now changes the player's position.

Other clients also need to see that change.

That is where:

NetworkTransform

helps.

It synchronizes position, rotation, and other Transform properties across networked instances.

The full flow becomes:

Player Input
    ↓
MoveRpc
    ↓
Server Moves Player
    ↓
NetworkTransform
    ↓
Other Clients See Movement

At this point, you already have the foundation of server-controlled multiplayer movement.


Step 9: Add a NetworkVariable

Not every networked value should be sent as an RPC.

Suppose you want to synchronize a player's score.

You can use:

public NetworkVariable<int> Score =
    new NetworkVariable<int>(0);

The server can update it:

if (IsServer)
{
    Score.Value += 1;
}

NetworkVariables are useful for persistent synchronized values such as:

Health
Score
Ammo
Team
Ready status
Match state

A simple rule is:

RPC → Something happened

NetworkVariable → Something has a state

For example:

Player fired weapon → RPC

Player health = 75 → NetworkVariable

Step 10: Test Two Players Locally

For multiplayer development, test with at least two running instances.

Start one instance as:

Host

and another as:

Client

You should see both players on each instance:

Host
├── Player 1
└── Player 2

Client
├── Player 1
└── Player 2

Move Player 1 and verify that only Player 1 responds.

Then move Player 2 and confirm the same behavior.


Step 11: Test the Important Scenarios

Before adding more multiplayer features, validate the basic networking behavior.

Host Starts

Expected:

Host session starts
Player 1 spawns

Client Connects

Expected:

Player 2 joins
Both players appear

Player Ownership

Move one player.

Expected:

Only the owner controls that player

State Synchronization

Change a NetworkVariable.

Expected:

The updated value appears
on connected clients

These checks help confirm that the fundamentals are working correctly before you expand the project.


RPC vs NetworkVariable

Choosing the correct synchronization method is important.

Use RPCs for events

Examples:

Shoot
Open door
Press button
Interact
Play effect

Use NetworkVariables for state

Examples:

Health
Score
Team
Ammo
Match status

Using each for its intended purpose keeps networking code cleaner and easier to maintain.


Common Unity Netcode Mistakes

Forgetting the NetworkObject

Any GameObject that needs network synchronization should generally include a NetworkObject.

Ignoring Ownership

Always check ownership before processing local player input.

if (!IsOwner)
    return;

Trusting the Client Too Much

For important gameplay actions, validate them on the server.

Synchronizing Everything

Every synchronized value consumes network bandwidth.

Only synchronize data that other clients actually need.

Testing With One Player

A multiplayer feature can appear correct with one instance and fail as soon as another client joins.

Starting With Matchmaking Too Early

First prove the core networking flow.

Then add:

Relay
Lobby
Matchmaking
Dedicated Servers
Authentication

Your First Netcode Architecture

At this stage, your multiplayer setup looks like:

             NetworkManager
                   │
            Unity Transport
                   │
       ┌───────────┴───────────┐
       ↓                       ↓
     Host                    Client
       │                       │
       └───────────┬───────────┘
                   ↓
            NetworkObjects
                   ↓
           NetworkBehaviour
             ┌─────┴─────┐
             ↓           ↓
            RPC     NetworkVariable
             ↓           ↓
           Events       State

This simple structure is the foundation for much larger multiplayer games.


What Should You Build Next?

Once local multiplayer works reliably, expand gradually:

Phase 1: Connection
Phase 2: Movement
Phase 3: Health & Score
Phase 4: Shooting
Phase 5: Player Spawning
Phase 6: Relay
Phase 7: Lobby
Phase 8: Matchmaking
Phase 9: Dedicated Servers

Building one system at a time keeps your networking architecture easier to test and debug.


Final Thoughts

Your first multiplayer implementation does not need to include complex matchmaking, prediction, dedicated servers, or advanced lag compensation.

Start with four concepts:

Connect → Own → Communicate → Synchronize

A successful first Unity netcode tutorial should prove that:

Two players can connect
        ↓
Each controls their own object
        ↓
Gameplay requests reach the server
        ↓
State is synchronized

Once this works, you have a strong foundation for combat, lobbies, Relay, matchmaking, prediction, and dedicated multiplayer servers.

Keep the first implementation simple, understand who owns each object, and expand the multiplayer architecture one system at a time.