Skip to content

Reliable vs Unreliable RPC Budget

Reliable is a delivery promise, not a free "make multiplayer work" button. Use it for rare messages that must arrive, not for Tick, held input, aim spam, or state that should have been replicated.

At a glance

Use this for: choosing Reliable, Unreliable, RepNotify, or local prediction for beginner network events - Main rule: reliable traffic is a budget - Best default: durable results as replicated state, low-frequency requests as reliable, frequent/cosmetic events as unreliable or local - Official docs: Remote Procedure Calls, Network Debugging, and Testing and Debugging Networked Games

The one-minute version

  • RPCs are one-way network messages. They do not return a value across the network.
  • Reliable means the networking layer keeps trying to deliver the RPC while the connection is alive.
  • Reliable does not mean instant, validated, cheat-proof, ordered against all other gameplay systems, or safe to call every frame.
  • Backed-up reliable traffic can delay later reliable messages on that channel.
  • Unreliable means the message may be dropped. That is acceptable for disposable or frequently refreshed data.
  • If the result must still be correct for late joiners or newly relevant clients, use replicated state or RepNotify instead of relying on a one-time RPC.
  • A beginner project should treat reliable RPCs as a small budget for low-frequency requests and important notifications.

What Reliable buys

Reliable buys delivery attempt and ordering within the reliable stream for that actor/channel path. It is useful when losing the message would break the feature:

Client:
    clicks Ready once
    -> ServerSetReady(true) Reliable

Server:
    validates lobby state
    sets PlayerState.bReady = true

If the packet has to be resent, the player may see latency, but the request is important enough to keep.

Reliable does not buy:

  • server trust;
  • bandwidth;
  • instant response;
  • immunity from bad ownership;
  • a return value;
  • correct state for late joiners;
  • permission to call from Tick.

The server still validates every client request.

What Unreliable is for

Unreliable is for messages where the next update or local fallback matters more than an old missed packet.

Good unreliable candidates:

  • cosmetic impact pings where the next impact can replace the old one;
  • repeated remote aim/look updates if you choose an RPC path;
  • footstep, muzzle, trail, or camera-style cues that are not gameplay truth;
  • short-lived animation or audio cues for currently relevant clients;
  • debug-only network markers during development.

Unreliable is not "bad." It is honest. Some messages are disposable.

The decision table

Event / data Better first choice Why
Press ready in lobby Reliable Server RPC -> replicated PlayerState Rare request; durable result.
Open shared door Reliable Server RPC request -> RepNotify door state Request matters; open state must persist.
Fire hitscan weapon Reliable or rate-limited Server RPC request -> replicated ammo/hit result Request matters, but do not spam without cooldown.
Hold automatic fire Local input loop + rate-limited server fire requests/state One reliable RPC per Tick will clog.
Aim direction every frame Unreliable updates, compressed replicated state, or Character/weapon state Old aim packets are usually stale.
Footstep sound Local/AnimNotify presentation, maybe unreliable multicast Missing one footstep is acceptable.
Health value Replicated/RepNotify variable Current value matters after packets/events are gone.
Explosion destroyed barrel RepNotify destroyed state + optional multicast FX The visual is transient; destroyed state is durable.
Private "purchase failed" message Reliable or normal Client RPC if rare Only owning client needs the result.

When in doubt, ask:

If this exact message is lost, can the next state update repair it?
If a late client joins, does it need to know this happened?
How many times per second can this graph call the RPC?

Held input and Tick

The common beginner bug:

Input Fire Triggered or Tick:
    ServerFire Reliable

If this runs every frame while the button is held, a short lag spike can build a reliable backlog. The player releases fire, but old reliable fire requests are still queued.

Better shapes:

Semi-auto:
    one press -> ServerFire once
    server enforces cooldown

Automatic:
    local held-input state starts a fire timer
    fire timer sends requests at weapon fire rate, not frame rate
    server validates cooldown/ammo

Continuous aim:
    send compressed aim at a fixed low rate
    use unreliable or replicated state depending on design

Rate limits are not polish. They are part of the network contract.

Reliable is not validation

A reliable client request can still be false, stale, or malicious.

Client:
    Reliable ServerTryPickup(PickupActor)

Server must still check:
    actor exists
    pickup is relevant/valid
    player is close enough
    line of sight or overlap is still valid
    inventory has space
    pickup not already consumed

Reliable only helps the request arrive. The server decides whether the request is accepted.

Ordering is narrower than beginners expect

Reliable RPCs preserve ordering on the relevant network path, but gameplay systems around them can still surprise you:

  • a replicated variable update and an RPC may be observed in an order your Blueprint did not mentally model;
  • different actors/components have different channels and timing;
  • network emulation can expose assumptions that only worked under zero lag;
  • a late client can receive current replicated state without ever receiving the earlier transient RPC.

If two values must be interpreted together, replicate one struct or state enum. If an RPC depends on a state value, include the minimum data the receiver needs or make the receiver read a durable replicated state after it arrives.

Fire, reload, and ammo examples

Good semi-auto request

Owning client:
    Input Fire Started
    -> local muzzle/camera prediction if desired
    -> ServerFire(AimData) Reliable or rate-limited

Server:
    validate weapon, cooldown, ammo, aim, team
    decrement replicated ammo
    apply hit or spawn projectile
    set replicated fire sequence / impact state as needed

Clients:
    update ammo/UI from RepNotify
    play confirmed impact/firing presentation

Bad automatic fire

Tick:
    if bHoldingFire:
        ServerFire Reliable

This ties network traffic to frame rate. Under packet loss, old fire requests can pile up.

Better automatic fire

Client:
    bHoldingFire local
    fire timer ticks at weapon fire interval
    local prediction plays cautiously
    ServerFire request at fire interval

Server:
    rejects if cooldown/ammo does not allow it
    replicated ammo/current fire state is the truth

The weapon fire rate, not the monitor refresh rate, controls the request rate.

When it fails, and what failure looks like

Symptom Likely cause
Game feels worse after checking Reliable Reliable messages are being spammed and backing up.
Remote client action still does nothing The actor is unowned/non-replicated, so reliability never made the RPC eligible.
Late joiner misses an important result You used a one-time RPC instead of replicated durable state.
Player fires after releasing input Old reliable fire requests were queued during lag.
Health UI misses intermediate hits Health should be state plus optional hit sequence/cue, not only transient RPCs.
Multicast did not reach a client The actor was not relevant to that client when the multicast was sent.
Server accepts impossible action Reliable request was delivered but not validated.
Network emulation breaks the feature The graph assumed zero latency or no packet loss.

Debug by printing RPC name, actor, net mode, authority, owning connection path, timestamp/sequence if you use one, and whether the server accepted or rejected the request. Then test with packet lag/loss after the basic no-emulation path works.

What Reliable does not do

  • It does not fix missing ownership.
  • It does not make a non-replicated actor carry RPCs.
  • It does not make Multicast global.
  • It does not validate client input.
  • It does not make high-frequency traffic free.
  • It does not preserve durable state for late joiners.
  • It does not avoid the need for RepNotify/UI refresh.
  • It does not guarantee a good user experience under latency.

Lookalikes - which one do I want?

Tool Use when Not for
Reliable Server RPC Low-frequency owning-client request must reach server. Tick, held input spam, or unvalidated gameplay.
Unreliable RPC Transient/frequent event can be dropped. Durable game state.
Replicated variable Clients need the current value. One-time sound/particle pulse.
RepNotify Clients need local presentation when state arrives. Client-to-server requests.
Run on Owning Client RPC Server sends private feedback to one owner. Public score/objective truth.
Multicast RPC Server sends a transient cue to relevant clients now. Late-join-safe state.
Local prediction Owning client needs immediate feel before server result. Final authority.
Timer/rate limiter Held input should produce fixed-rate requests. Per-frame networking.

The quick path is to mark every RPC Reliable. The concrete cost is hidden traffic debt: the game can feel less responsive exactly when the network gets worse. Spend Reliable on messages that deserve it.

Going deeper