Learn Godot - Multiplayer & Networking
Series/Learn Godot/Episode 13
Episode 13 of 23

Learn Godot - Multiplayer & Networking

Bringing the game online: Godot's high-level multiplayer API with the ENet transport, RPC and state synchronization through MultiplayerSynchronizer, the authoritative server versus peer-to-peer patterns, and the basics of lag compensation and network security so the multiplayer game isn't easy to cheat.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 12, you polished the game with animation, particles, and shaders — the game now feels alive. Episode 13 raises the stakes: making your game playable together. We build multiplayer with Godot's high-level API, which hides the complexity of TCP/UDP sockets, so you spend more time writing game logic than network protocols.

This episode's roadmap: get to know the high-level multiplayer API and the ENet transport, build a simple lobby with host and join, use RPC to call functions across machines, synchronize state with MultiplayerSynchronizer, then finish with the authoritative server versus peer-to-peer patterns and the basics of lag compensation and network security.

High-Level API and the ENet Transport

Godot has a high-level multiplayer API: a set of nodes and methods that handle connections, serialization, and routing automatically. You don't need to write byte buffers yourself — just define what data to send, and Godot takes care of it.

Behind the scenes, its default transport is ENet, a UDP-based networking library with a reliability layer. ENet gives fast, UDP-like delivery while also ensuring important messages arrive like TCP. In Godot 4, the class used is ENetMultiplayerPeer. (In Godot 3, this class was named NetworkedMultiplayerENet — if you read older tutorials, that's the old name.)

There are three core components: MultiplayerAPI (the routing brain), MultiplayerPeer (the transport, filled by ENet), and helper nodes like MultiplayerSynchronizer and MultiplayerSpawner for automatic synchronization.

Host and Join with ENetMultiplayerPeer

The most basic pattern is one player becoming the host (server and client at once) and other players joining their address. Create an autoload node named Net so the whole game can access the connection:

PythonBecoming the host on a specific port
func jadi_host(port: int = 9999) -> void:
    var peer := ENetMultiplayerPeer.new()
    peer.create_server(port, 4)
    multiplayer.multiplayer_peer = peer
 
func on_peer_connected(id: int) -> void:
    print("Pemain masuk dengan ID ", id)
on_peer_connected is only called on the host
PythonJoining the host
func gabung(ip: String, port: int = 9999) -> void:
    var peer := ENetMultiplayerPeer.new()
    peer.create_client(ip, port)
    multiplayer.multiplayer_peer = peer
create_client uses the host's IP and port

Each client is identified by a peer ID: the host is always 1, and clients are given a unique ID after joining. This ID is used to route messages to a specific player. Connect the peer_connected and peer_disconnected signals from multiplayer to catch players entering and leaving.

Info

Connection signals (peer_connected) are only triggered on the host. A client knows its connection succeeded via MultiplayerAPI.connection_succeeded. Get in the habit of checking is_server() before adding a player to the game list.

RPC: Calling Functions Across Machines

RPC (Remote Procedure Call) is the way to call a function on another machine as if it were local. In Godot 4, a function is marked with the @rpc annotation, then called via rpc() or rpc_id():

PythonRPC to switch scenes together
@rpc("any_peer", "call_local")
func muat_level(level: int) -> void:
    get_tree().change_scene_to_file("res://levels/level_%d.tscn" % level)
 
func minta_ganti_level(level: int) -> void:
    rpc("muat_level", level)
call_local so the host executes too

@rpc accepts several modes: any_peer (anyone may call) versus authority (only the authority may), call_local (the caller executes too), and reliable (use the reliable transport) versus unreliable. For positions updated every frame, use unreliable; for critical data like damage, use reliable.

State Synchronization with MultiplayerSynchronizer

Spreading rpc calls for every position change would flood the network. For state that changes continuously, Godot 4 provides MultiplayerSynchronizer: a node that registers another node's properties, then automatically sends their latest values to other peers several times per second.

Place a MultiplayerSynchronizer as a child of the player node, register the target node in the root_path property, then register the properties you want synchronized:

PythonSynchronizing position and rotation
$MultiplayerSynchronizer.root_path = get_path()
$MultiplayerSynchronizer.update_interval = 0.05
$MultiplayerSynchronizer.replication_config
update_interval controls how often values are sent

For objects created at runtime — bullets, spawned enemies — pair it with MultiplayerSpawner: every instance added to the scene tree on the creating machine is automatically recreated on other machines. With Spawner + Synchronizer, most action games can be synchronized without writing manual network code.

Authoritative Server vs Peer-to-Peer Patterns

The most important architecture question: who determines the game's truth? There are two big patterns:

  • Peer-to-peer: all players are equal, each sending state to everyone. Easy to set up, but no party "acts as a witness" — vulnerable to cheating and desynchronization.
  • Authoritative server: one machine (the host) computes the entire logic — position, damage, loot — and clients only send intent. Clients display the results. This is the industry standard for competitive games.

In Godot, the authoritative server pattern means physics and damage code only run on the host, while clients send actions and receive results. A small example: the client sends a "jump" command, the host executes it:

PythonClient sends intent, server executes
@rpc("any_peer")
func minta_lompat() -> void:
    if multiplayer.is_server():
        karakter.melompat()
any_peer lets clients request; execution stays with the authority

Even though peer-to-peer is easier for prototypes, build your game with the authoritative server pattern from the start — moving it later will be far more painful.

Lag Compensation and Network Security

On real networks, packets arrive with latency — not instantly. MultiplayerSynchronizer helps with interpolation, but for action games you need a few lag compensation techniques:

  • Client-side prediction: the client projects its own movement immediately without waiting for the server, reducing the feeling of "lag."
  • Reconciliation: client state is compared against server state and corrected when the server sends the truth.
  • Interpolation: other objects' positions are rendered between two updates so their movement is smooth, not choppy.

Security follows: because all data passes through the network, you can't trust clients. The basic rules:

  • Validate all input on the server — never trust positions sent by clients.
  • Don't send unnecessary data: limit bandwidth with unreliable and a reasonable update_interval.
  • Think about rate limiting: cap the number of requests per second so one player can't flood the server.
  • Encryption at the transport level (TLS) for sensitive games; for prototypes, focus on validation first.

Warning

Godot's high-level API isn't anti-cheat. It simplifies communication, but all authority still depends on your design. The simplest rule that saves many games: "the server is the only source of truth, clients are only senders of intent."

Conclusion

Episode 13 took you from zero to functional multiplayer: ENetMultiplayerPeer as the ENet-based transport, the host and join patterns with peer IDs, @rpc for calling functions across machines, MultiplayerSynchronizer and MultiplayerSpawner for automatic synchronization, a comparison of the authoritative server versus peer-to-peer patterns, and the basics of lag compensation and network security rules.

The key takeaways:

  • Godot 4's default multiplayer transport is ENetMultiplayerPeer; in Godot 3 it's named NetworkedMultiplayerENet.
  • Use @rpc for rare events and MultiplayerSynchronizer for continuously changing state.
  • The host is always is_server() and has peer ID 1; clients get a unique ID after joining.
  • The authoritative server pattern is harder at first, but the only way to protect game integrity.
  • Validate all input on the server; clients can never be trusted.

In episode 14, after the game can be played together, you face a new question: why does the game feel heavy on your machine? We dissect performance & profiling — optimizing draw calls and batching, physics, the built-in profiler, memory usage and FPS, up to optimization at export time. A fast game isn't luck; it's the result of measurement.

Learn Godot - Multiplayer & Networking | Learn Godot