Godot Version
Godot 4.3-Stable
Question
I’m having trouble replicating a map/level/terrain over to the client.
I’m using a MultiplayerSpawner node called MapSpawner
that has the root Game
Node3D as it’s path, terrain.tscn
scene in the Auto Spawn List, and 0 for the Spawn Limit.
My idea with the MapSpawner is that the client starts first, loads the terrain.tscn
and has it set under the MapSpawnPoint Node3D, as shown in the remote debug:
I thought the MapSpawner node would be able to replicate the TerrainGeneration node over to the client with no issue?
Notice how the map ground mesh or anything isn’t loaded in for the client. Yet the client can recognize and collide into terrain.
Terrain loads in just fine with only host spun up:
No terrain passed in from the MultiplayerSpawner:
Here is how I generate terrain only if it is multiplayer authority:
extends Node
class_name TerrainGeneration
func _ready():
if is_multiplayer_authority():
generate()
func generate():
... generation code form noisemap...
Here is what calls the above TerrainGeneration code, only if multiplayer authority again:
extends Node3D
@onready var world_scene = preload("res://scenes/levels/terrain.tscn")
var current_world: Node = null # Variable to keep track of the current world
@onready var map_spawn_point: Node3D = $World/MapSpawnPoint
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
if is_multiplayer_authority():
# Instantiate the world for the multiplayer authority
instantiate_world()
# Function to instantiate the world and replace the old one
func instantiate_world() -> void:
# Remove the previous world if it exists
if current_world:
current_world.queue_free()
current_world = world_scene.instantiate()
map_spawn_point.add_child(current_world)
And here is my multiplayer_manager, adding people to the game:
extends Node
@export var _player_spawn_point: Node3D
var _multiplayer_scene = preload("res://scenes/characters/humans/base_human.tscn")
var _boat_scene = preload("res://scenes/objects/boats/jon_boat/Jon_Boat.tscn")
var _players_in_game: Dictionary = {}
func _ready():
# need this to allow time for the callbacks to be established
await get_tree().process_frame
if NetworkManager.is_hosting_game:
print("Network lifecicle setup")
multiplayer.peer_connected.connect(_client_connected)
multiplayer.peer_disconnected.connect(_client_disconnected)
# NOTE: can comment this out if you want to test locally as a dedicated server (no client)
if not OS.has_feature("dedicated_server"):
_add_player_to_game(1)
func _add_player_to_game(network_id: int):
print("Adding player to game: %s" % network_id)
var player_to_add = _multiplayer_scene.instantiate()
player_to_add.name = str(network_id)
_players_in_game[network_id] = player_to_add
_player_spawn_point.add_child(player_to_add)
func _remove_player_from_game(network_id: int):
print("Removing player from game: %s" % network_id)
if _players_in_game.has(network_id):
var player_to_remove = _players_in_game[network_id]
if player_to_remove:
player_to_remove.queue_free()
_players_in_game.erase(network_id)
func _ready_player(player: HumanNode):
var boat_to_add = _boat_scene.instantiate()
player.position = Vector3(50.5, 4, -2)
boat_to_add.position = Vector3(50.5, 3, -2)
# Connection lifecycle
func _client_connected(network_id: int):
print("Client connected %s" % network_id)
_add_player_to_game(network_id)
func _client_disconnected(network_id: int):
print("Client disconnected %s" % network_id)
_remove_player_from_game(network_id)
Any idea where to go from here? Thanks in advance