Note: Everything may still change, if you need something stable and documented to depend on, use Godot 3.x/stable.
Last updated: 2021-10-06
Ask questions in #networking
on chat.godotengine.org
Relevant Pull Requests (look at all):
- https://godotengine.org/article/multiplayer-changes-godot-4-0-report-1
- https://github.com/godotengine/godot/commit/24a949ea1154a2298e6898c53fdb75178affe098
- Multiplayer renames/simplification: godotengine/godot#52480
- Spawn/despawn sync: godotengine/godot#51097 and godotengine/godot#51534
- State sync: godotengine/godot#51788
- Renames: godotengine/godot#51481 and godotengine/godot#50398
close_connection()
is silent now: godotengine/godot#52342- By default, all peers can now call RPC methods, whereas previously it was only
master
: godotengine/godot#51301 - Channels are now supported in MultiplayerPeer: godotengine/godot#51005
- Mesh networking and lowlevel wrappers for ENet: godotengine/godot#50710
- RSETs got removed: godotengine/godot#49221
- Tons of fixes and improvements :)
- MultiplayerAPI is now used instead of things like signals being on the SceneTree directly: https://docs.godotengine.org/de/latest/classes/class_multiplayerapi.html
network
has been removed where possible in MultiplayerAPI due to redundancy, e.g.multiplayer.is_network_server()
is now justmultiplayer.is_server()
, exception are the methods inNode
, wheremultiplayer
is used instead, see below:Node.set_network_master()
is nowNode.set_multiplayer_authority()
- The
TransferMode
andRPCMode
enums are now bound as core constants, which means instead ofMultiplayerAPI.RPC_MODE_ANY
you can just useRPC_MODE_ANY
# Create peer
var peer = ENetMultiplayerPeer.new()
# Connect some signals if you want them
peer.peer_connected.connect(_peer_connected)
peer.peer_disconnected.connect(_peer_disconnected)
peer.connection_failed.connect(_connection_failed)
peer.connection_succeeded.connect(_connection_succeeded)
# (You can also connect to get_tree().multiplayer.peer_connected and so on,
# that works even while the peer is null)
# peer.create_server(SERVER_PORT)
peer.create_client(SERVER_IP, SERVER_PORT)
# Assign peer to multiplayer API
# Multiplayer API now has most relevant functions, have a look at get_tree().multiplayer
get_tree().multiplayer.network_peer = peer
RSETs are gone, just use RPCs now.
You use the @rpc
annotation to denote RPC functions.
You can use arguments with that annotation for configuration, in any order.
Arguments are:
- sync/nosync (whether calls are called locally too, or only remote)
- any/auth (whether the RPC can be called by any peer or only
auth
, the authority (previouslymaster
) - reliable/unreliable/ordered (transfer mode)
Examples:
remote func test()
becomes
@rpc
test()
remotesync func test()
becomes
@rpc(any, sync)
test()
mastersync
would now be @rpc(auth, sync)
.
You can also still use Node.rpc_config()
:
rpc_config(&'move_and_slide', RPC_MODE_ANY)
This enabled scene spawning/syncing replication for the scenes "Player" and "Box".
For both, spawns are synced, so if you .instantiate()
them and add them to the scene, that gets done on all other peers automatically as well, same for .queue_free()
ing/deleting them.
For "Player", position
is kept synced as well, so if you move, position
gets updated on peers.
For real use, you want to use a custom RPC for movement (to be able to interpolate the position and smooth updates).
But this is useful to keep less important things synchronized.
func _ready():
_replication_setup(Player, ["position"], true)
_replication_setup(Box, ["position"])
func _replication_setup(scene : PackedScene, params : Array, sync : bool = false):
# Scenes are identified using the new resource UIDs
var id = ResourceLoader.get_resource_uid(scene.resource_path)
# Enable spawn/despawn syncing
multiplayer.replicator.spawn_config(
id,
MultiplayerReplicator.REPLICATION_MODE_SERVER,
params
)
if sync:
# Enable property syncing
multiplayer.replicator.sync_config(id, 16, params)