Godot Version
4.6.1.stable
Question
I’m trying to set up a system for a P2P multiplayer game using Steam’s lobbies system (using GodotSteam addon). It seems like server relay isn’t supported with SteamMultiplayerPeer, so I have been having to write some workarounds to send information from the clients to the host and then back to the other clients.
This is not a competitive game and will primarily be played in groups of people who already know each other (think friendslop), so I am simplifying my work by making each player the authority for their own movement (position, rotation, velocity, etc.). I thought the best approach for this would be to just use a MultiplayerSynchronizer to sync these properties from the client to the host, and another MultiplayerSynchronizer to sync them back from the host to the other clients (again, can’t use relay, so one synchronizer doesn’t work). However, just doing that means that the values the host has will also be sent to the player who should be the authority for their own movement, meaning that they effectively can’t move.
I figured I should use visibility to make it so the values are synced from the server to all the clients except for the one that “owns” those values, but the visibility methods aren’t very well documented and so I’m having a difficult time getting it to work. Am I supposed to call set_visibility_for() just server-side? Client-side too? Right now I have this (in the level code, which spawns the players):
## Create a player character for a peer. Register the character as belonging
## to that peer, and spawn it in. The MultiplayerSpawner will ensure the
## character is spawned for all peers as well.
func _create_player_chara(peer: int) -> void:
var player_chara: Node3D = player_scene.instantiate()
if multiplayer.multiplayer_peer is not OfflineMultiplayerPeer:
var steam_id := (multiplayer.multiplayer_peer as SteamMultiplayerPeer).get_steam_id_for_peer_id(peer)
var steam_username := Steam.getFriendPersonaName(steam_id)
player_chara.get_node("Graphics/Nametag").text = steam_username
player_chara.peer_id = peer
player_chara.name = PLAYER_CHARA_NAME_PREFIX + str(peer)
# Filter to disable visibility for only the client who has authority over this
# player character.
player_chara.get_node("ServerPosRotVelSynchronizer").add_visibility_filter(func(id: int) -> bool:
return id != peer
)
add_child(player_chara, true)
This code is called only from the host, and the spawns are synced with a MultiplayerSpawner. The ServerPosRotVelSynchronizer is the MultiplayerSynchronizer that is supposed to send the info from the server to all the clients except the one who owns that player character, so that’s what the filter is supposed to do. The synchronizer has public_visibility set to false, and visibility_update_mode is Idle. However, when checking visibility on the player character using get_visibility_for(), it returns false.
What am I missing lol…? I would expect visibility to be synced automatically, but do I need to add this filter client-side, too, or something?