Implementing System so players know they're facing one another. (With 3D Sprites, In Online Multiplayer)

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

Update:
I’ve gotten incredibly close to figuring it out. Now the only issue is that the sprite changes are only occurring in the host’s session and not the clients.


I’ve been trying to implement a system that allows players to tell if they’re facing one another while using 3D sprites. The idea is, if two players face one another then they will see their front sprites, however, if player 1 views player 2 and player 2 is facing away from player 1 then player 1 will see player 2’s back sprite.

Here is what I have for my code so far:

Player Script

   extends CharacterBody3D
var sprite:CompressedTexture2D
var front_texture = preload ("res://art/Knight_Front.tres")
var back_texture = preload ("res://art/Knight_Back.tres")
var speed: float = 3
var mouse_sensitivity: float = 0.005  # adjust this value to your liking
var accept_mouse_input: bool = true
const JUMP_VELOCITY: float = 3
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
var pitch: float = 0
var yaw: float = 0
var camera: Camera3D


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

func _ready():
	if not is_multiplayer_authority(): return
	
	camera = get_node("Camera1")
	Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
	camera.current = true
	rpc("announce_presence")
	
func _input(event):
	if accept_mouse_input:
		if event is InputEventMouseMotion:
			yaw -= event.relative.x * mouse_sensitivity
			pitch -= event.relative.y * mouse_sensitivity
			pitch = clamp(pitch, -PI / 2, PI / 2)

func _physics_process(delta):
	if not is_multiplayer_authority(): return
	
	if Input.is_action_just_pressed("ui_accept") and is_on_floor():
		velocity.y = JUMP_VELOCITY
	
	if !is_on_floor():
		velocity.y -= gravity * delta
	
	var input_dir = Input.get_vector("Left", "Right", "Up", "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()
	
	rotation_degrees.y = rad_to_deg(yaw)
	camera.rotation_degrees.x = rad_to_deg(pitch)
	
	for player in get_tree().get_nodes_in_group("players"):
		print("Player name: ", player.name, " Type: ", typeof(player))
		if player != self:
			if is_looking_at(player) and player.is_in_front_of(self):
				player.change_sprite_to_front()
			else:
				player.change_sprite_to_back()
	
	
func _unhandled_input(event):
	if not is_multiplayer_authority(): return
	if Input.is_action_just_pressed("ShowMouse"):
		Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
	if Input.is_action_just_pressed("HideMouse"):
		Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func change_sprite_to_front():
	var sprite_node = get_node("sprite")
	sprite_node.texture = front_texture
	
func change_sprite_to_back():
	var sprite_node = get_node("sprite")
	sprite_node.texture = back_texture
	
func is_looking_at(other: CharacterBody3D) -> bool:
	var my_forward = -self.global_transform.basis.z.normalized()
	var to_other = (other.global_transform.origin - self.global_transform.origin).normalized()
	var dot_product = my_forward.dot(to_other)
	var fov_rad = deg_to_rad(camera.fov / 2)
	return dot_product > cos(fov_rad)

func is_in_front_of(other: CharacterBody3D) -> bool:
	var my_forward = -self.global_transform.basis.z.normalized()
	var to_other = (other.global_transform.origin - self.global_transform.origin).normalized()
	var dot_product = my_forward.dot(to_other)
	var fov_rad = deg_to_rad(75 / 2)
	return dot_product > cos(fov_rad)

func print_players_in_group():
	for player in get_tree().get_nodes_in_group("players"):
		print(player.name)
		
	
@rpc("any_peer") func announce_presence():
	add_to_group("players")

Main Scenes Script:

extends Node3D

const Player = preload("res://player.tscn")
@onready var main_menu = $Menu/CanvasLayer/MainMenu
@onready var address_entry = $Menu/CanvasLayer/MainMenu/MarginContainer/VBoxContainer/AddressEntry
const PORT = 27015
var enet_peer = ENetMultiplayerPeer.new()


func _on_host_button_pressed():
	main_menu.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_join_button_pressed():
	main_menu.hide()
	enet_peer.create_client("localhost", PORT)
	multiplayer.multiplayer_peer = enet_peer

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