1
\$\begingroup\$

I am using Mirror for doing my little multi-player car racing project which I want to rename the game object automatically after the NetworkManager auto create the game object.

Here is my NetworkManager code:

using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class MyNetworkManager : NetworkManager
{
    public List<GameObject> spawnPos;
    
    public override void OnServerAddPlayer(NetworkConnection conn)
    {
        Transform start = spawnPos[numPlayers].transform;
        GameObject player = Instantiate(playerPrefab, start.position, start.rotation);
        player.name = "car_" + (numPlayers + 1).ToString();
        NetworkServer.AddPlayerForConnection(conn, player);
    }

}

This NetworkManager works good in the Host PC. However, when the client connecting to the host, the name showing in the inspector on client PC is still like car(Clone).

Does anyone know how to deal with this problem?

Thank you for your help.

\$\endgroup\$
2
  • \$\begingroup\$ "which need to name after the objects name before player connects to the game." — I'm having trouble parsing this. Can you rephrase? Name what after the object's name? What object? \$\endgroup\$ – doppelgreener Jan 16 at 12:23
  • \$\begingroup\$ @doppelgreener sorry for misunderstanding. What I wanna do is using NetwrokManager to auto create player car and rename the player car immediately. As a result, I override OnServerAddPlayer this function to rename the game object after Instantiate. But it doesn't work \$\endgroup\$ – CDY Jan 16 at 12:54
1
\$\begingroup\$

You can use a syncVar for the player name.

[SyncVar]
public string playerName;

You have to set the playerName on the server. The clients will automatically get notified of the changes to playerName.

\$\endgroup\$
1
  • \$\begingroup\$ This looks like overkill for simply getting GameObjects like "car_1" numbered consistently as it seems OP is attempting to do. \$\endgroup\$ – DMGregory Jan 16 at 13:34
1
+200
\$\begingroup\$

welcome to the GameDev Stack Exchange. It looks like your code currently only runs server side which is pretty normal for most projects when initially creating players and setting up the scene. This should keep your server up to date with the latest information, however it does not send these updates to clients.

Usually when setting shared variables you need to plan for sending updates to 1.) the server, 2.) clients already in game, 3.) new clients joining the game. Most online tutorials will help you with the first 2 but the 3rd case is usually the most difficult (you can do this by either resetting all player names when someone joins or by using [TargetRpc]).

An easy way to take care of this is using the [SyncVar] property which will send regular updates to every client/server about property updates. This can be helpful if a variable is constantly changing but as @DMGregory suggests, can be overkill in most cases. Usually in this scenario you will need to tell the server to let clients know the name has changed and that they should update their local version of the players name to match the new players name

Below is roughly what I would do to try an keep names synchronized (you may need to fiddle with it because like most code on StackExchanges, it isn't really properly tested and is just there to give you an idea of how to solve the problem). This may seem like a lot of code, but the idea is that by updating the players name only when needed you can keep your network connection free for sending more important updates like player positions.

using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class MyNetworkManager : NetworkManager
{
    public List<GameObject> spawnPos;

    public override void OnServerAddPlayer(NetworkConnection conn)
    {
        Transform start = spawnPos[numPlayers].transform;
        GameObject player = Instantiate(playerPrefab, start.position, start.rotation);

        NetworkServer.AddPlayerForConnection(conn, player);

        int playerId = PlayerManager.Instance.players.Count() - 1;
        string name = "car_" + playerId.ToString();
        PlayerManager.Instance.SetPlayerName(playerId, name);
    }
}

public class PlayerManager : NetworkBehaviour
{
    public PlayerManager Instance; // Quick and dirty singleton, you can find better implementations later
    public List<Player> players = new List<Player>();

    public void Awake()
    {
        Instance = this;
    }

    // Call this when you want to change a players name
    public void SetPlayerName(int playerId, string name)
    {
        CmdSetPlayerName(playerId, name);
    }

    // Tell server name to let people know a name has changed
    [Command]
    private void CmdSetPlayerName(int playerId, string name)
    {
        players[playerId].SetPlayerName(name); // update my player name value
        RpcSetPlayerName(playerId, name); // tell clients to update value
    }

    // tell client to update their own copy of the players name
    [ClientRpc]
    private void RpcSetPlayerName(int playerId, string name)
    {
        players[playerId].SetPlayerName(name); // update my player name value
    }
}

public class Player : MonoBehaviour
{
    private void Awake()
    {
        PlayerManager.players.Add(this);
    }

    // Actually update players name.
    public void SetPlayerName(string name)
    {
        gameObject.name = name;
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.