Skip to main content

🌐 Lesson 10.1: The Multiplayer Model — Roles, Ownership & Authority

Networking is where many Unreal programmers stall — not because it's hard code, but because the mental model is unfamiliar. Master three ideas — authority, roles, and ownership — and the rest is syntax. This lesson builds that model and cashes in every "server-only" hint the course has dropped.

🎯 Learning Objectives

By the end of this lesson, you will be able to:

  • Explain Unreal's client-server architecture and server authority
  • Check authority with HasAuthority() and branch code accordingly
  • Identify the network roles (Authority, AutonomousProxy, SimulatedProxy)
  • Explain ownership and why it gates RPCs
  • Distinguish listen server, dedicated server, and client net modes

Estimated Time: 60 minutes

Engine Version: Unreal Engine 5.8

In This Lesson

Client-Server & Authority

Unreal multiplayer is client-server, not peer-to-peer. One machine is the server — the single source of truth. Clients send input to the server and receive updates back. The server decides what's real; clients display it.

graph TD S["SERVER (authority)
the real game state"] S -->|"replicates state"| C1["Client 1 (a copy)"] S -->|"replicates state"| C2["Client 2 (a copy)"] C1 -->|"sends input / requests"| S C2 -->|"sends input / requests"| S
Figure 1: The server owns the truth and pushes state to clients; clients send requests up. This one-way authority is the foundation of everything in this module.

📖 Authority = "the server's copy is the real one"

The machine with authority over an actor gets to make real decisions about it — apply damage, change score, spawn. On clients, actors are replicated copies that mostly display what the server tells them. This is why cheating is harder: a client can lie about its own screen, but the authoritative server has the final say on game state. It's also why GameMode is server-only (Lesson 3.1) and Possess must run on the server (Lesson 4.3) — those were previews of exactly this principle.

Checking Authority

Because the same C++ runs on server and clients, you constantly need to ask "am I the authority here?" That's HasAuthority().

void AEnemy::TakeDamage(float Amount)
{
    // Only the server may change authoritative game state.
    if (!HasAuthority())
    {
        return;   // a client must NOT change health directly — ask the server (RPC, Lesson 10.3)
    }

    Health -= Amount;          // safe: we're the authority
    if (Health <= 0.0f)
    {
        Destroy();             // destroying an actor is a server decision
    }
}

⚠️ Gameplay-changing code must be authority-guarded

Applying damage, spawning, destroying, changing score — these must happen on the server. Wrapping them in if (HasAuthority()) ensures a client running the same function can't corrupt shared state. A client that wants something to happen doesn't do it directly; it asks the server via a Server RPC (Lesson 10.3). Getting this guard wrong is the root of most multiplayer bugs.

✅ The three-part networking pattern

Almost every networked action follows: (1) client asks the server (RPC), (2) server changes authoritative state, (3) that state replicates back to all clients (properties). This lesson sets up the roles; 10.2 covers step 3, 10.3 covers step 1, and 10.4 assembles all three.

Network Roles

Every replicated actor has a role on each machine, describing that machine's relationship to it. The three you'll meet:

RoleMeaningExample
ROLE_AuthorityThis machine owns the truth for this actorAny actor, on the server
ROLE_AutonomousProxyA client controlling this actor (gets prediction)Your own pawn, on your client
ROLE_SimulatedProxyA client just displaying this actorAnother player's pawn, on your client
graph TD subgraph Server SA["Your pawn: Authority"] SB["Their pawn: Authority"] end subgraph YourClient["Your client"] CA["Your pawn: AutonomousProxy"] CB["Their pawn: SimulatedProxy"] end
Figure 2: The same pawn has different roles on different machines. On the server everything is Authority; on your client, your pawn is AutonomousProxy (you drive it) and others are SimulatedProxy (you just watch them).

📖 Why AutonomousProxy is special

Your own pawn gets ROLE_AutonomousProxy so the engine can do client-side prediction — moving you immediately on your machine rather than waiting a round-trip to the server (which would feel laggy). The Character Movement Component (Lesson 4.2) does this automatically. Other players' pawns are SimulatedProxy — you just interpolate what the server reports. Check the role with GetLocalRole()/GetRemoteRole() when behavior should differ.

Ownership

Ownership is the connection between a client and the actors it's allowed to command. A PlayerController owns its pawn; that ownership chain is what lets a client send RPCs about that pawn. The server enforces it — a client can't send a Server RPC on an actor it doesn't own.

⚠️ Ownership gates client → server RPCs

A Server RPC (Lesson 10.3) only works if the calling client owns the actor it's called on. Your PlayerController owns your Pawn, so a Server RPC on your Pawn is allowed. Try to call one on an actor you don't own and the engine drops it. This is why player-controlled logic lives on owned actors (Pawn/PlayerController) — the same "who owns what" thinking as Lesson 4.3's Controller-vs-Pawn split, now enforced by the network.

✅ The ownership chain

Connection → PlayerController → Pawn → (attached/owned actors). Set ownership with SetOwner (recall FActorSpawnParameters::Owner from Lesson 3.4 — that's exactly this). A weapon owned by your character is owned, transitively, by you — so you can send Server RPCs about it.

Net Modes

Finally, the shapes a running instance can take — the net mode:

Net ModeWhat it is
NM_StandaloneSingle-player — no networking (everything is authority)
NM_ListenServerA player's machine acts as both server and a client
NM_DedicatedServerA server with no local player (pro/hosted)
NM_ClientA pure client connected to a server

✅ Test with multiple clients in PIE

In the editor you can set Number of Players and Net Mode in the Play settings to run a listen server plus clients right in PIE — invaluable for testing replication without deploying a server. A key habit: test networked features early and often in multi-client PIE, because "works in Standalone" tells you nothing about whether replication is correct. Single-player is NM_Standalone where HasAuthority() is always true — which is why bugs hide until you go multiplayer.

Hands-on Exercise & Quiz

🏋️ Exercise: Reason about authority

Objective: Apply the model before writing replication code.

  1. A client presses "fire." Where should the actual damage be applied, and how does the request get there?
  2. On your client, what role does your own character have? What role does another player's character have?
  3. Why can you send a Server RPC on your own pawn but not on an enemy you don't own?
  4. Which net mode is single-player, and why do networking bugs hide there?
✅ Answers
  • 1. Damage is applied on the server (authority). The client sends a Server RPC (10.3) requesting the shot; the server validates and applies it.
  • 2. Yours = AutonomousProxy (you control it, gets prediction); theirs = SimulatedProxy (you just display it).
  • 3. Server RPCs require ownership; your PlayerController owns your pawn but not the enemy, so the engine drops an RPC on an un-owned actor.
  • 4. NM_Standalone. HasAuthority() is always true there, so missing authority guards and replication never manifest until you run a real client-server session.

🎯 Quick Quiz

Question 1: Who is the single source of truth in Unreal multiplayer?

Question 2: Code that applies damage should be guarded with:

Question 3: On your client, another player's character has which role?

Summary

🎉 Key Takeaways

  • Unreal multiplayer is client-server: the server holds authoritative truth and replicates it to clients, who send requests up.
  • Guard authoritative changes (damage, spawn, destroy, score) with HasAuthority() — this is why GameMode is server-only and Possess is a server action.
  • Roles: Authority (server truth), AutonomousProxy (your predicted pawn), SimulatedProxy (others you display).
  • Ownership (Connection → Controller → Pawn) gates client → server RPCs — you can only command actors you own.
  • Net modes: Standalone / ListenServer / DedicatedServer / Client — test networked features in multi-client PIE, since Standalone hides replication bugs.

📚 Additional Resources

🚀 What's Next?

You have the model. Now step 3 of the pattern — getting server state to clients automatically: property replication and RepNotify, so a replicated health value updates every client's HUD without you writing any sync code.

🎉 Lesson complete!

The mental model is set. Let's replicate some state.