How do I synchronize multiplayer input?

Godot Version

Godot 4

Question

following this tutorial https://youtu.be/V4a_J38XdHk?t=1367 at roughly that chapter, he does the thing to like synchronize the input direction, but i don’t know how to replicate it in my project since im doing 3d and i have different movement (for example I don’t have only 1 variable “direction”, but I also have “input_dir” etc)

This is my current character script (equivalent to his multiplayer_controller script basically):

extends CharacterBody3D

@onready var camera = $Camera3D
@onready var skeleton_3d = $metarig/Skeleton3D

const SPEED = 10
const JUMP_VELOCITY = 10

var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
var MouseSensivity = 0.002
var camerarotation = Vector2(0,0)

@export var player_id := 1:
    set(id):
        player_id = id

func _apply_animations(delta):
    if velocity.x == 0 and velocity.z == 0:
        $AnimationPlayer.play("Idle")
    else:
        $AnimationPlayer.play("walk")

func _apply_movement_from_input(delta):

    if not is_on_floor():
        velocity.y -= gravity * delta

    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = JUMP_VELOCITY


    var input_dir = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
    if direction:
        velocity.x = direction.x * SPEED
        velocity.z = direction.z * SPEED

    else:
        velocity.x = move_toward(velocity.x, 0, SPEED)
        velocity.z = move_toward(velocity.z, 0, SPEED)


    move_and_slide()

func _ready():
    Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _input(event):
    if event.is_action_pressed("ui_cancel"):
        Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
    if event.is_action_pressed("leftclick"):
        Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

    if event is InputEventMouseMotion:
        var MouseEvent = event.relative *MouseSensivity
        CameraLook(MouseEvent)

func CameraLook(Movement: Vector2):
    camerarotation += Movement
    camerarotation.y = clamp(camerarotation.y, -1.5,1.2)

    transform.basis = Basis()
    camera.transform.basis = Basis()

    rotate_object_local(Vector3(0,1,0), -camerarotation.x)

func _physics_process(delta):
    if multiplayer.is_server():
        _apply_movement_from_input(delta)

    if not multiplayer.is_server() || MultiplayerManager.host_mode_enabled:
        _apply_animations(delta)

Any help would be appreciated, let me know if more information are needed.

It would be very similar, the only difference I can see is using Input.get_vector for 3D instead of Input.get_axis for the x axis. You can follow along seamlessly.

This method of multiplayer will cause tremendous input lag and potentially desynchronize players, usually it’s better to synchronize positions directly and check if movements are valid on the server if you want to catch cheaters.

Thanks so much, so for synchronizing position and rotation is enough to do it in the replication tab of the multiplayer synchronizer?

1 Like

Yes, with set_multiplayer_authority(id)

The player must be an authority of their CharacterBody3D to replicate

What is an authority exactly?

Who is allowed to edit what. It is used by the RPC configs and synchronizers. By default the server is authority of everything, individual players and components must be changed with set_multiplayer_authority(id)

Could you show me a code example or help me implement it in my code to better understand? Thanks btw

They go over it in the tutorial linked. You would apply it to the Character script instead of the input component they make.

@export var player_id: int = 1:
    set(id):
        player_id = id
        set_multiplayer_authority(id)
        # instead of: %InputSynchronizer.set_multiplayer_authority(id)
1 Like

here is the tutorial guy code in case

okkk then what should i do in the synchronizer for synchronizing position and rotation? just syncing in the replication tab?

1 Like

Yes, syncing in the replication tab

1 Like

Man. Im gonna try this now. you dont know how much you helped me. thanks so much

Btw MultiplayerManager.host_mode_enabled is giving me errors, any suggestion? I have no idea of what this is and its invalid apparently (and if i remove it the client just cant move)

I am not sure why that’s in the code, host_mode_enabled is used once and the same as multiplayer.is_server(). Where it’s used creates a strange is_server or not is_server condition that should always be true.

I recommend removing it

1 Like

thanks man, life saver :pray:

wait, now its just

func _physics_process(delta):
	_apply_movement_from_input(delta)
	_apply_animations(delta)

and for some reason i can control both players from server and from client i can control only server. is this supposed to happen right now and i just have to continue the tutorial or am i missing something

You will have to continue the tutorial, they talk about disabling the physics_process and process functions for non-authority characters. Something along these lines to look out for

func _ready() -> void:
    if not is_multiplayer_authority():
        set_process(false)
        set_physics_process(false)
2 Likes

Thanks

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.