Hello everybody! I’m having problems synchronizing the player’s playername with other clients, I start the server and enter through the client, the name appears above my player, but when I use another client the names are buggy, both player1 and player2 the ui of nametext does not follow each one individually.
I would like some help getting the nametext UI to follow each unique player and see other players and their name following the same. 2d top down mmorpg style
Any help and thank you very much!
> Edit: Canvasprefab is in screen space - overlay because in worldscreen it bugs the position of the canvas
Script playercontroller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
using TMPro;
using System;
public class PlayerController : NetworkBehaviour
{
[Header("--------- COMPONENTS ---------")]
public Rigidbody2D rbPlayer;
public Animator anim;
public GameObject parentCamera;
public Camera mainCamera;
public Controller mvJoystick;
[Header("--------- OTHERS ---------")]
public GameObject nameCanvasPrefab; // Referência ao prefab do Canvas
private GameObject nameUIInstance; // Instância da UI
private TextMeshProUGUI playerNameText;
private Canvas nameCanvas;
[Header("--------- PLAYER ---------")]
[SyncVar(hook = nameof(OnNameChanged))] public string playerName = "Player";
[SyncVar] public Guid playerID;
[SyncVar] public float currentHealth;
public float maxHealth = 100f;
public float playerSpeed = 2f;
private Vector2 direction;
// Start is called before the first frame update
void Start()
{
if (isLocalPlayer)
{
parentCamera.SetActive(true);
mvJoystick.gameObject.SetActive(true);
CmdSetPlayerName("Player " + netId); // Exemplo: definir um nome único com o ID da rede
}
else
{
parentCamera.SetActive(false);
mvJoystick.gameObject.SetActive(false);
}
// Criar a UI do nome diretamente para o cliente
CreatePlayerNameUI();
}
// Update is called once per frame
void Update()
{
if (nameUIInstance != null)
{
// Atualiza a posição da UI para seguir o jogador
Vector3 screenPosition = Camera.main.WorldToScreenPoint(new Vector3(transform.position.x, transform.position.y + 1.0f, 0));
nameUIInstance.transform.position = screenPosition;
}
if (isLocalPlayer)
{
HandleMovement();
CmdUpdatePlayerPosition(transform.position); // Envia a posição ao servidor
}
HandleAnimation();
DestroyPlayerIfNeeded();
}
private void HandleAnimation()
{
anim.SetFloat("Horizontal", direction.x);
anim.SetFloat("Vertical", direction.y);
anim.SetFloat("SpeedV", direction.sqrMagnitude);
if (direction != Vector2.zero)
{
anim.SetFloat("IHorizontal", direction.x);
anim.SetFloat("IVertical", direction.y);
}
}
private void HandleMovement()
{
rbPlayer.velocity = new Vector2(mvJoystick.joyvec.x * playerSpeed, mvJoystick.joyvec.y * playerSpeed);
direction = rbPlayer.velocity.normalized;
}
private void DestroyPlayerIfNeeded()
{
if (currentHealth <= 0)
{
CmdDestroyPlayer();
}
}
// ------------------------------------------------------------------------------------------------------
#region Commands
[Command]
public void CmdSetPlayerName(string newName)
{
playerName = newName; // Isso acionará o hook OnNameChanged automaticamente
}
[Command]
private void CmdDestroyPlayer()
{
NetworkServer.Destroy(gameObject);
}
[Command]
private void CmdUpdatePlayerPosition(Vector3 newPosition)
{
// Atualiza a posição e chama o RPC para todos os clientes
RpcUpdatePlayerPosition(newPosition);
}
#endregion Commands
// ------------------------------------------------------------------------------------------------------
#region ClientRPCs
[ClientRpc]
private void RpcUpdatePlayerPosition(Vector3 newPosition)
{
// Atualiza a posição do jogador para todos os clientes
if (!isLocalPlayer)
{
transform.position = newPosition;
}
}
#endregion ClientRPCs
// ------------------------------------------------------------------------------------------------------
#region Methods
private void CreatePlayerNameUI()
{
if (nameCanvasPrefab != null)
{
nameUIInstance = Instantiate(nameCanvasPrefab);
nameCanvas = nameUIInstance.GetComponent<Canvas>();
playerNameText = nameUIInstance.GetComponentInChildren<TextMeshProUGUI>();
playerNameText.text = playerName;
// Inicializa a posição correta do Canvas
Vector3 screenPosition = Camera.main.WorldToScreenPoint(new Vector3(transform.position.x, transform.position.y + 1.0f, 0));
nameUIInstance.transform.position = screenPosition;
}
else
{
Debug.LogError("NameCanvasPrefab não atribuído no PlayerController!");
}
}
void OnNameChanged(string oldName, string newName)
{
if (playerNameText != null)
{
playerNameText.text = newName; // Atualiza o texto na UI quando o nome mudar
}
}
private void OnDestroy()
{
if (nameUIInstance != null)
{
Destroy(nameUIInstance);
}
}
#endregion Methods
}