Skip to main content

๐Ÿ“ž Lesson 10.3: RPCs โ€” Server, Client & Multicast

Properties push state down; RPCs โ€” Remote Procedure Calls โ€” let you invoke a function on another machine. A client asks the server to fire a weapon; the server tells everyone to play the effect. Three RPC types cover every direction, and once you know which is which, networked actions become straightforward.

๐ŸŽฏ Learning Objectives

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

  • Distinguish Server, Client, and NetMulticast RPCs by direction
  • Declare and implement an RPC with the _Implementation pattern
  • Choose Reliable vs Unreliable appropriately
  • Add server-side validation with WithValidation
  • Combine RPCs with replication to build a networked action

Estimated Time: 60 minutes

Engine Version: Unreal Engine 5.8

In This Lesson

Three Directions

An RPC is declared with a UFUNCTION specifier that names where it runs. The three:

graph TD SR["Server RPC
called on client โ†’ RUNS on server"] CR["Client RPC
called on server โ†’ RUNS on owning client"] MC["NetMulticast RPC
called on server โ†’ RUNS on server + all clients"]
Figure 1: The three RPC types by direction. Server = "client asks server"; Client = "server tells one client"; Multicast = "server tells everyone".
SpecifierCall it onRuns onUse for
ServerThe owning clientThe serverClient requests an action (fire, interact)
ClientThe serverThat actor's owning clientServer notifies one player (you leveled up)
NetMulticastThe serverServer + all clientsBroadcast a cosmetic event (explosion FX)

๐Ÿ“– The direction is everything

The mistake newcomers make is calling an RPC on the wrong machine. A Server RPC does nothing if you call it on the server (it's already there); a Multicast called on a client does nothing (only the server can multicast). Always ask: "who is calling this, and where should it run?" โ€” then pick the matching specifier.

Server RPCs

The workhorse: a client asks the server to do something authoritative. Declared with Server, defined in a _Implementation function (the same suffix pattern as BlueprintNativeEvent, Lesson 6.1).

// Weapon.h
// Server = runs on server; Reliable = guaranteed; WithValidation = anti-cheat check.
UFUNCTION(Server, Reliable, WithValidation)
void ServerFire(const FVector& Direction);
// Weapon.cpp
// The actual body goes in _Implementation:
void AWeapon::ServerFire_Implementation(const FVector& Direction)
{
    // This runs on the SERVER, with authority (Lesson 10.1).
    // Do the real, authoritative work: trace, apply damage, spend ammo.
    // ...then Multicast the cosmetic effect (next section)...
}

// _Validate runs on the server BEFORE _Implementation โ€” reject cheating.
bool AWeapon::ServerFire_Validate(const FVector& Direction)
{
    // Return false to drop the RPC and flag the client as misbehaving.
    return Direction.IsNormalized();   // e.g. reject a malformed direction
}

You call it plainly from the client โ€” Unreal routes it to the server:

// On the client (e.g. from input, Lesson 4.1):
void AWeapon::TryFire()
{
    const FVector Dir = GetAimDirection();
    ServerFire(Dir);   // looks like a normal call; actually runs on the server
}

โš ๏ธ Ownership + validation

A Server RPC only reaches the server if the client owns the actor (Lesson 10.1) โ€” call it on your own pawn/weapon, not an un-owned actor. WithValidation requires a _Validate function that returns false to reject bad calls (never trust the client โ€” validate the request). This ownership + validation pairing is your first line of anti-cheat.

Multicast & Client RPCs

Once the server has done authoritative work, it often needs to tell others. NetMulticast tells everyone (great for cosmetic effects); Client tells one specific player.

// NetMulticast: the server calls it, it runs on server + all clients.
UFUNCTION(NetMulticast, Unreliable)
void MulticastPlayFireFX();

void AWeapon::MulticastPlayFireFX_Implementation()
{
    // Runs everywhere โ€” play muzzle flash, sound, tracer on every machine.
    PlayFireEffects();
}

// Client: the server calls it, it runs only on the owning client.
UFUNCTION(Client, Reliable)
void ClientNotifyLevelUp(int32 NewLevel);

void APlayerState::ClientNotifyLevelUp_Implementation(int32 NewLevel)
{
    // Runs only on THAT player's client โ€” show their personal level-up UI.
}

โš ๏ธ Multicast is server-called only

A NetMulticast RPC must be invoked on the server (typically from inside a Server RPC's _Implementation). Calling it on a client does nothing. And use multicasts for cosmetic, transient events (effects, sounds) โ€” not authoritative state, which belongs in replicated properties (Lesson 10.2). Multicasting core state instead of replicating it is a common design mistake.

Reliable vs Unreliable

Every RPC is Reliable or Unreliable โ€” a real performance/correctness trade-off:

ReliableUnreliable
GuaranteeAlways arrives, in orderMay be dropped
CostMore bandwidth & bookkeepingCheap
Use forImportant actions (fire, take damage, buy)Frequent cosmetic updates (footstep FX)

โœ… The guideline

Reliable for anything gameplay-affecting that must not be lost โ€” a shot, a purchase, a death notice. Unreliable for high-frequency cosmetic events where an occasional miss is invisible โ€” a muzzle flash, a footstep sound. Overusing Reliable clogs the channel; using Unreliable for critical actions loses them. Match reliability to consequence.

The Full Fire Pattern

Now the three-part pattern from Lesson 10.1 in complete code โ€” a networked weapon fire:

// 1) CLIENT presses fire โ†’ asks the server (Server RPC).
void AWeapon::TryFire()
{
    if (!CanFire()) { return; }
    ServerFire(GetAimDirection());   // routes to server
}

// 2) SERVER does the authoritative work, then tells everyone the cosmetic part.
void AWeapon::ServerFire_Implementation(const FVector& Dir)
{
    // Authoritative (server): trace + apply damage + spend ammo.
    --CurrentAmmo;                                   // replicated (Lesson 10.2)
    FHitResult Hit;
    if (TraceShot(Dir, Hit))                          // trace (Lesson 5.2)
    {
        if (UHealthComponent* HC = Hit.GetActor()->FindComponentByClass<UHealthComponent>())
        {
            HC->ApplyDamage(Damage);                  // server-authoritative
        }
    }
    // 3) Tell everyone to play the effect (Multicast).
    MulticastPlayFireFX();
}

bool AWeapon::ServerFire_Validate(const FVector& Dir) { return Dir.IsNormalized(); }

void AWeapon::MulticastPlayFireFX_Implementation()
{
    PlayFireEffects();   // muzzle flash + sound on server & every client
}

โœ… The canonical shape

Client requests (Server RPC) โ†’ server changes authoritative state (replicated properties) โ†’ server broadcasts cosmetics (Multicast RPC). Ammo replicates down to update HUDs (10.2 + 9.2); damage flows through the replicated health component to every client's health bar; the muzzle flash multicasts to all. Every networked feature you build is a variation on this shape โ€” the capstone of this module (10.4) walks a full one end to end.

Hands-on Exercise & Quiz

๐Ÿ‹๏ธ Exercise: A networked interact

Objective: Route an interaction through RPCs.

  1. A client presses "interact" on a door. Write the Server, Reliable, WithValidation RPC ServerInteract(AActor* Target) on the player's pawn.
  2. In _Implementation, verify authority and call the door's interface Execute_Interact (Lesson 5.5) โ€” which toggles the replicated bIsOpen (Lesson 10.2).
  3. How does the door's new open state reach the other clients โ€” RPC or replication?
  4. Should ServerInteract be Reliable or Unreliable? Why?
โœ… Answers
  • 3. Replication โ€” the server toggles the replicated bIsOpen, which replicates down; each client's OnRep_IsOpen plays the animation. Don't multicast the state itself.
  • 4. Reliable โ€” interacting is a discrete gameplay action that must not be dropped; a lost interact would feel broken.

๐ŸŽฏ Quick Quiz

Question 1: A client wants the server to apply damage. It uses a:

Question 2: A NetMulticast RPC must be called on:

Question 3: A frequent, purely-cosmetic footstep effect RPC should be:

Summary

๐ŸŽ‰ Key Takeaways

  • RPCs run a function on another machine: Server (clientโ†’server), Client (serverโ†’owning client), NetMulticast (serverโ†’everyone).
  • Declare with a UFUNCTION specifier; put the body in Fn_Implementation; call the plain name.
  • Server RPCs need ownership and should use WithValidation + a _Validate function โ€” never trust the client.
  • Multicast is server-called and for cosmetic events; authoritative state belongs in replicated properties, not multicasts.
  • Use Reliable for critical actions, Unreliable for frequent cosmetics; the canonical flow is Server RPC โ†’ replicate state โ†’ Multicast cosmetics.

๐Ÿ“š Additional Resources

๐Ÿš€ What's Next?

You have all three networking tools โ€” authority, replication, and RPCs. The module finale ties them into one complete replicated gameplay feature, walked end to end, so you see the whole pattern working together.

๐ŸŽ‰ Lesson complete!

Commands fly in every direction. Let's build a full networked feature.