Godot 4 Top Down Multiplayer: How to handle mouse look with MultiplayerSynchronizer?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By myersguy

To begin, I was following this tutorial, which I modified to fit a 2d top down game instead. Everything in the tutorial (moving, I left out jumping given the nature of the game) has worked great to this point.

The tutorial uses a MultiplayerSynchronizer for the User Inputs, and then handles all of the movement on the player based on the synchronized values.

PlayerInput:

extends MultiplayerSynchronizer
@export var direction := Vector2()

func _ready():
	set_process(get_multiplayer_authority() == multiplayer.get_unique_id())

func _process(delta):
	direction = Input.get_vector( "ui_left", "ui_right", "ui_up", "ui_down")

Player

extends CharacterBody2D

const SPEED = 300.0

@export var player := 1 :
	set(id):
		player = id
		$PlayerInput.set_multiplayer_authority(id)

@onready var input = $PlayerInput

func _physics_process(delta):
	var direction = (Vector2(input.direction.x, input.direction.y)).normalized()
	if direction:
		velocity.x = direction.x * SPEED
		velocity.y = direction.y * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)
		velocity.y = move_toward(velocity.y, 0, SPEED)

	move_and_slide()
	
func _ready():
	if player == multiplayer.get_unique_id():
		$Camera2D.make_current();

What I can’t figure out for the life of me is how to implement mouse look using this pattern. For single player, you would of course just use look_at(get_global_mouse_position()) on the player. However, it seems that I should be separating concerns and passing the mouse position (or similar) from PlayerInput to the Player.

What is the best (or any) way to go about this?

(And please let me know if this is a classic X/Y problem, and that I shouldn’t be trying to separate concerns this way)

:bust_in_silhouette: Reply From: Hurde

I had the same problem. I solved it like this
For the player input script:

#player_input.gd
@export var angle := float(0)
var screen = Vector2.ZERO    

func _ready():
  screen = get_viewport().get_visible_rect().size
  screen = screen / 2

func _input(event):
if event is InputEventMouseMotion:
	var temp = Vector2(event.position)
	var mouse_rel = temp - screen
	angle = atan2(mouse_rel.y, mouse_rel.x) # returns an angle

For the character script:

#player.gd
@onready var input = $PlayerInput
$Skeleton/chest.rotation = input.angle #This would've been my look_at otherwise

And yes, I’ve added it as sync property too.

what happens is, we measure the game window, the MousEeventMotion returns an position on the screen, And based on those we calculate an angle, and we send that to our character.

Hope it helps ^^