Players cannot see other players objects

Godot Version

Godot v4.2.2.stable.mono - macOS 14.5.0 - Vulkan (Forward+) - integrated Apple M2 - Apple M2

Question

I’m trying to make Proof of Concept of a Multiplayer game, to know how Multiplayer works in Godot. I can see the players’ movement and rotation from the other player’s side, but, whenever a player is instantiated, it instantiates its own weapons, this makes the players able to load different weapons one from each other.

The problem is that the other players cannot see the other players’ weapons, as you can see in the following video:

This is the code where I instantiate the Characters:

extends Node

@onready var main_menu = $CanvasLayer/MainMenu
@onready var adress_entry = $CanvasLayer/MainMenu/MarginContainer/VBoxContainer/AdressEntry

const Character := preload("res://scenes/characters/character.tscn")
const PORT := 3000

var enet_peer := ENetMultiplayerPeer.new()

func add_character(peer_id: int) -> void:
	var character = Character.instantiate()
	character.name = str(peer_id)
	add_child(character)

func _on_host_btn_pressed():
	main_menu.hide()
	
	enet_peer.create_server(PORT)
	multiplayer.multiplayer_peer = enet_peer
	
	multiplayer.peer_connected.connect(add_character)
	add_character(multiplayer.get_unique_id())

func _on_join_btn_pressed():
	main_menu.hide()
	
	enet_peer.create_client("localhost", PORT)
	multiplayer.multiplayer_peer = enet_peer

And this is the Characters code (I removed the movement just to make the code shorter to share):

@tool
extends CharacterBody3D

var weapon_names: Array[String] = ["knife", "pistol"]

@onready var twist_pivot := $TwistPivot
@onready var pitch_pivot := $TwistPivot/PitchPivot
@onready var player := $Player
@onready var weapon = $Player/Weapon
@onready var camera = $TwistPivot/PitchPivot/Camera3D

const SPEED := 6.5
const JUMP_VELOCITY := 6.5

var weapons: Array[Node3D] = []
var active_weapon := 0

var mouse_mode := Input.MOUSE_MODE_CAPTURED
var mouse_sensitivity := 0.001
var twist_input := 0.0
var pitch_input := 0.0
var gravity := 20.0
var anim_weapon_player: AnimationPlayer = null

func set_weapon_names(new_weapon_names: Array) -> void:
	weapon_names.assign(new_weapon_names)

func load_weapon(w_name: String) -> Node3D:
	var weapon_path := "res://scenes/weapons/%s.tscn" % w_name

	if ResourceLoader.exists(weapon_path):
		return load(weapon_path).instantiate()

	return null

@rpc("call_local", "reliable")
func load_weapons() -> void:
	if not is_multiplayer_authority(): return

	weapons = []
	for w_name in weapon_names:
		var new_weapon = load_weapon(w_name)
		if new_weapon:
			weapons.append(new_weapon)

@rpc("call_local")
func set_weapon() -> void:
	if not is_multiplayer_authority(): return

	for n in weapon.get_children():
		weapon.remove_child(n)

	weapon.add_child(weapons[active_weapon])
	anim_weapon_player = weapons[active_weapon].get_node("AnimationPlayer")

@rpc("call_local")
func attack() -> void:
	if anim_weapon_player:
		anim_weapon_player.stop()
		anim_weapon_player.play("attack")

@rpc("call_local")
func change_weapon() -> void:
	if (active_weapon == weapons.size() - 1):
		active_weapon = 0
	else:
		active_weapon += 1

	set_weapon()

func _enter_tree():
	set_multiplayer_authority(name.to_int())

func _ready():
	if not is_multiplayer_authority(): return

	Input.set_mouse_mode(mouse_mode)
	load_weapons.rpc()
	set_weapon.rpc()
	camera.current = true

func _unhandled_input(_event: InputEvent) -> void:
	if not is_multiplayer_authority(): return

	if Input.is_action_just_pressed("attack") and \
			anim_weapon_player.current_animation != "attack":
		attack.rpc()


func _process(_delta: float) -> void:
	if Input.is_action_just_pressed("act_change_weapon"):
		change_weapon.rpc()

Any ideas of what is happening and how can it be fixed?

remove if not is_multiplayer_authority(): return

1 Like

It worked like this: I removed the if not is_multiplayer_authority(): return from set_weapon and load_weapons and in the _ready function, I moved the rpc calls of both functions above the if not is_multiplayer_authority(): return, like this:

func _ready():
	load_weapons.rpc()
	set_weapon.rpc()

	if not is_multiplayer_authority(): return

	Input.set_mouse_mode(mouse_mode)
	camera.current = true