How to replicate interactions and child scenes changes (Like a mesh change) in p2p multiplayer?

Godot Version

4.2.stable

Question

I am making a multiplayer game which has interactions.

If the player presses the interact button (“E”) when facing something he can interact with (This is done via a raycast which checks for collisions then calls an event via an eventBus), the mesh of the interacted object changes.

Now this works fine but when taking it into multiplayer everything becomes too complicated.

The change appears only to the player that executed the interaction.

I have tried everything I could find. From RPC functions to putting the script in the multiplayer synchronizer node. Nothing works, in fact it becomes worse.

Here is the main level script:

extends Node3D


const PORT = 9999
var enet_peer = ENetMultiplayerPeer.new()

var Player = preload("res://character_body_3d.tscn")

func _on_button_pressed():
	$CanvasLayer.hide()
	
	enet_peer.create_server(PORT)
	multiplayer.multiplayer_peer = enet_peer
	multiplayer.peer_connected.connect(add_player)
	
	add_player(multiplayer.get_unique_id())


func _on_button_2_pressed():
	$CanvasLayer.hide()
	
	enet_peer.create_client("localhost", PORT)
	multiplayer.multiplayer_peer = enet_peer


func add_player(peer_id = 1):
	var player = Player.instantiate()
	player.position.y = 1
	player.name = str(peer_id)
	add_child(player)

And heres the hierarchy for the main scene:

And heres the eventBus script (its just a script put on autoload)

extends Node

signal onPlayerInteract(object)

In the player script i just emit the signal when the button is pressed and the raycast is colliding.

And in the main script I connected the eventBus signal which changes the target mesh but it did not work. (It only changed it for the player who interacted and not globally) I did it like so:

func changeSkin(object):
	object.get_node("MeshInstance3D").mesh = preload("res://skin.obj")


My ultimate goal is to get the Timer node to be in sync if it was in another scene (Like initiate a timer node in another scene by one player but the timer is synced across both players and can be paused by anyone)

But for now figuring out how to sync the mesh would be enough to get me going, I would greatly appreciate any help since I have been stuck on this for the past 3 days. Thanks.

Can you include the code that you use to sync the changes with the other peers?

1 Like

Nvm i fixed the issue.

To solve it heres what i did for future readers:

In the player script make an RPC(“call_local”) function which emits the signal with what you are interacting with as the parameter. Make sure to call this as an rpc when the player interacts. (on input)

In the main script, connect the signal to a function which does the required operations on the received object.

Please note that the signal is defined in an EventBus script

And just like that, everything should be replicated. No need to do any extra steps

1 Like