Godot provides a comprehensive networking system for creating multiplayer games. The system is built around MultiplayerAPI for high-level multiplayer functionality and various peer implementations for different networking backends.
Godot’s multiplayer system uses a client-server architecture by default, where one peer acts as the authoritative server.
Server - Authoritative peer that manages game state (peer ID = 1)
Clients - Connect to the server and send/receive updates
Peer-to-Peer - All peers can communicate, but one is designated as server
# Check if running as serverif multiplayer.is_server(): print("Running as server")else: print("Running as client")# Get your unique peer IDvar my_id = multiplayer.get_unique_id()print("My peer ID: ", my_id)
// Check if running as serverif (Multiplayer.IsServer()){ GD.Print("Running as server");}else{ GD.Print("Running as client");}// Get your unique peer IDint myId = Multiplayer.GetUniqueId();GD.Print($"My peer ID: {myId}");
extends Node# Declare RPC function with annotation@rpc("any_peer", "call_local")func say_hello(message: String): print("Received message: ", message)func _ready(): # Call on all peers say_hello.rpc("Hello from " + str(multiplayer.get_unique_id())) # Call on specific peer say_hello.rpc_id(2, "Hello to peer 2")
public partial class MyNode : Node{ [Rpc(MultiplayerApi.RpcMode.AnyPeer, CallLocal = true)] private void SayHello(string message) { GD.Print($"Received message: {message}"); } public override void _Ready() { // Call on all peers Rpc(MethodName.SayHello, $"Hello from {Multiplayer.GetUniqueId()}"); // Call on specific peer RpcId(2, MethodName.SayHello, "Hello to peer 2"); }}
# Authority-only RPC (default)@rpc("authority")func server_function(): print("Only server can call this")# Any peer can call@rpc("any_peer")func anyone_can_call(): print("Anyone can call this")# Call locally as well as remotely@rpc("any_peer", "call_local")func call_everywhere(): print("Called on sender and receivers")# Unreliable transfer (faster but may be lost)@rpc("any_peer", "unreliable")func fast_update(): print("Fast but may be lost")# Unreliable ordered (fast but ordered)@rpc("any_peer", "unreliable_ordered")func ordered_fast_update(): print("Fast, may be lost, but ordered")
Use unreliable or unreliable_ordered for frequent updates like position that can tolerate packet loss.
extends CharacterBody2Dfunc _ready(): # Set authority to the peer that owns this player set_multiplayer_authority(name.to_int())func _process(delta): # Only process input if we're the authority if is_multiplayer_authority(): handle_input() move_and_slide()func handle_input(): var velocity = Vector2.ZERO if Input.is_action_pressed("move_right"): velocity.x += 1 if Input.is_action_pressed("move_left"): velocity.x -= 1 velocity = velocity.normalized() * 300
public partial class Player : CharacterBody2D{ public override void _Ready() { // Set authority to the peer that owns this player SetMultiplayerAuthority(int.Parse(Name)); } public override void _Process(double delta) { // Only process input if we're the authority if (IsMultiplayerAuthority()) { HandleInput(); MoveAndSlide(); } } private void HandleInput() { Vector2 velocity = Vector2.Zero; if (Input.IsActionPressed("move_right")) velocity.X += 1; if (Input.IsActionPressed("move_left")) velocity.X -= 1; Velocity = velocity.Normalized() * 300; }}
The MultiplayerPeer is the low-level networking backend:
# Create and configure peervar peer = ENetMultiplayerPeer.new()# Start as servervar error = peer.create_server(8080, 4) # Port 8080, max 4 clientsif error != OK: print("Failed to create server") returnmultiplayer.multiplayer_peer = peerprint("Server started on port 8080")
// Create and configure peervar peer = new ENetMultiplayerPeer();// Start as serverError error = peer.CreateServer(8080, 4); // Port 8080, max 4 clientsif (error != Error.Ok){ GD.Print("Failed to create server"); return;}Multiplayer.MultiplayerPeer = peer;GD.Print("Server started on port 8080");