Switching between multiple scenes in multiplayer with multiple clients.

Godot Version
4.2.2

Question
Hello, I’m currently developing a game where 2 or more players can join a server created when a player presses “HOST” in the main menu. This functionality works smoothly; all players can walk, type in chat, and attack without issues.

I have created a changeScene object attached to an Area2D node with the following script:
"extends Area2D

@export var scene = “res://scenes/insideHouse.tscn”
@export var button = “ui_accept”

var entered = false
var currentPlayerName

func _on_body_entered(body):
if body.is_in_group(“players”):
currentPlayerName = str(body.get_name())
entered = true

func _on_body_exited(body):
if body.is_in_group(“players”):
entered = false

func _process(_delta):
if entered and Input.is_action_just_pressed(button):
GlobalStats.PlayerName = str(currentPlayerName)
rpc(“changeS”)

@rpc(“any_peer”, “call_local”)
func changeS():
if GlobalStats.PlayerName == str(currentPlayerName) and str(multiplayer.get_unique_id()) == currentPlayerName:
print_debug(GlobalStats.PlayerName)
get_tree().change_scene_to_file(scene)"
This script detects collisions between players and the changeScene object, allowing players to press ENTER to transition to a different scene. However, a problem arises here: players can independently change scenes, and if one player (the host) transitions, it disconnects other players not entering the new scene, which is unintended.

I want all players to be able to join different scenes and stay synchronized. Currently, I cannot rejoin the same scene after changing it, and the host gets stuck in the main scene. Below are the functions for hosting and joining the server:
"func _on_host_button_pressed():
main_menu.hide()
username.hide()
enet_peer.create_server(PORT)
enet_peer.get_host().compress(ENetConnection.COMPRESS_RANGE_CODER)
multiplayer.set_multiplayer_peer(enet_peer)
multiplayer.peer_connected.connect(add_player)
multiplayer.peer_disconnected.connect(remove_player)

add_player(multiplayer.get_unique_id())

# Assign username to the player
usrnm = username.text

func _on_join_button_pressed():
main_menu.hide()
username.hide()

enet_peer = ENetMultiplayerPeer.new()
enet_peer.create_client(address_entry.text, PORT)
enet_peer.get_host().compress(ENetConnection.COMPRESS_RANGE_CODER)
multiplayer.multiplayer_peer = enet_peer

# Assign username to the player
usrnm = username.text

func add_player(peer_id):
var player = player_scene.instance()
player.name = str(peer_id)
game.add_child(player)

func remove_player(peer_id):
var player = get_node_or_null(str(peer_id))
if player:
player.queue_free()
"
In summary, I need assistance ensuring that all players can join different scenes and remain synchronized. Currently, players can change scenes independently, and the host remains stuck in the main scene after transitioning.

1 Like

This is your main problem. When the scene changes on the host, the scene trees no long align with the clients and RPCs will break because nodes will changes node paths. Host and client need to be almost mirrors of each other.

I think it’s also obliterating your enet instance.

What you need to do is have all scenes run at the same time on the host and the player nodes jump to each scene branch when they do so.

Best practice is to have player MultiplayerSpawner nodes for each scene so when a player leaves one scene and enters another all you have to do on the host is remove and add child between the scenes.

Obviously it’s not good practice to have scenes run when no player is in it. So you need to dynamically add remove scenes depending on the players.

The host will need to have all the scenes running, but the client only needs the one it’s in. But it’s important that the scene tree layout matches the hosts version.

1 Like