Can't find a way of getting player ids

Hey there,

so I’m developing a multiplayer game and I was able to give players different ids by using a syncvar and making the player count how many players there were, this then made them know wich player they are by know how many players are connected. The thing is, I added a lobby to the game and now everyone connects at the same time wich destroyed my old system. I’ve searched everywhere but can’t seem to find a way of getting a player’s unique ID. The docs are 5 word long for every command , so reading it didn’t get me very far… I saw that the lobby players have a unique NetworkID on the inspector but when I tried to access it , it returned me 0 for the host and nothing for the client wich seems very strange to me. I also found that NetworkIdentity.netId returns an error that says that I cannot simply convert it to an int.

NetID is the only way I would go. If you are using lobbyManager then there are two kinds of prefabs:

  • LobbyPrefab
  • GamePrefab

When you join to the lobby then LobbyPrefab is created which has it’s own NetID and after the scene is changed it spawns the GamePrefab with second unique NetID (both of them working simultaneously). I you get the 0 you had to access it before there were spawned (the only thing it comes to my mind, I had similar problem but with gamePrefab netID, lobbyPrefab was always right).

Second thing is that NetID is type of uint (usigned integer, it starts from 0, no negatives values) that’s why you couldn’t convert it. Anyway better way is to display it with .ToString() method.

Thank you very much, it did after quite a few test work, but the thing is that I was unable to do it from the GamePrefab since the LobbyPrefabs loses the isLocalPlayer attribute, so, I had to make the LobbyPrefab tell the GamePrefab wich Player he is.

In the process I had to use the Update function for this, since the OnLevelWasLoaded function was only being called server-side

I’m also using my CustomLobbyManager and I use OnLobbyServerCreateGamePlayer.
To retrieve the netID from just spawned gamePrefab you go like this:

    public override GameObject OnLobbyServerCreateGamePlayer(NetworkConnection conn, short playerControllerId)
    {
        GameObject gamePlayer;
        gamePlayer = (GameObject)Instantiate(gamePlayerPrefab, NetworkLobbyManager.singleton.GetStartPosition().position, NetworkLobbyManager.singleton.GetStartPosition().rotation);

        NetworkServer.Spawn(gamePlayer);
        NetworkInstanceId gamePlayerNetID = gamePlayer.GetComponent<NetworkIdentity>().netId;

        return gamePlayer;
    }

hey, I Though this issued was solved. I did it in a lot of different ways and the best one I could find was this one :

On a delayed start function ( so it has time to properly initialize )

PlayerBaseID = Convert.ToInt32(GetComponent<NetworkIdentity>().netId.Value) - GameObject.Find("NetManager").GetComponent<NetworkManager>().numPlayers;

But the thing is, sometimes without changing any code, some of the player ids are 1, 2 ,3 and 4, and sometimes it’s something like, 1, 2, 316, 326

What’s happening ? Why isn’t it something linear? Why is it so freaking dificult to return a simple ID ??

What do you need the unique player id for?

I have 4 players, each one has a different race and an identifier so I can check who interacted with who, where to spawn each one , wich race to give to each one , etc…

I think I found out why, it’s starting to make sense, I have already spawned serverobjects that apparently have an id, maybe sometimes players take too much time to connect and end up having theire netid updated after all those other objects. Would there be a way of prioritizing the player objects ?

Just to document this for future devs who happen to stumble across this.

PROBLEM :
I figured out why it wasn’t working every single time. netid is a variable that also exists in non spawned objects. In this case, I have a objects lying around my game scene that were not player authority objects. Sometimes these loaded faster than the players leaving them with the netids 1,2,3 and 4 and pushing the player’s ids to 300 - 400.

SOLUTION :
To fix this issue I created a loading screen. This one I have applyed to the NetLobbyManager as the game scene. Wich means that now My player objects are spawning on an empty level. Their netids are going to be the ammount of players connected ( Lobby Player Objects ) + (Game Player Objects ). This is where I get the netId - numPlayers. After that, I load the game scene with the player set to DontDestroyOnLoad having the id variable already loaded up. On the player I check if I’m on the correct scene and if I am I now load all of the settings I have to.

My solution is quite unconventional and probably not very optimized neither correct in a big environment, but in my case it’s for a collage project and code is not going to be graded, only gameplay , art and bugs. Since this doesn’t generate any issues for what I’m after, I’ll leave it this way.

Thank you both for your help!

I think you’re doing things way too complicated! If you need all the players in a List, its the simplest thing:

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using System.Collections.Generic;

public class Player : NetworkBehaviour {

    //Since this is static, you can now access this list of active players from every other place in your code by typing "Player.ActivePlayers".
    //If you need to work with indices, you can also use a List instead. (ie ActivePlayers[0].DoBackflip())
    public static HashSet<Player> ActivePlayers = new HashSet<Player>();

    protected virtual void Awake()
    {
        //Add me when I awake - this is called on both the clients and the host, so everyone will know me
        ActivePlayers.Add(this);
    }

    protected virtual void OnDestroy()
    {
        //Cleanup - this is important since static members will persist until application is quit
        ActivePlayers.Remove(this);
    }

}

When you have some kind of manager script, you can now access all the players from there, its just “Player.ActivePlayers”.

Edit: I read you want to identify your players by numbers (1, 2, 3, 4). The HashSet won’t work with indices, but a List will do. You just have to keep in mind that the sorting will vary on each client because they will fill and empty the list independetly. So you really should internally rely on their NetIds.
What you can do is, you can sort the List based on all active players netIds:
using System.Linq;
And after adding a new player:
ActivePlayers = ActivePlayers.OrderBy(item => item.netId).ToList();
(probably move the Add-Part to Start() then, cause netId might not yet be initialized on Awake())

Edit Edit: While that might work, its probably not what you want. Just do this instead:

    [SyncVar]
    int PlayerId = -1;

    protected virtual void Start()
    {
        ActivePlayers.Add(this);
        if (isServer)
            PlayerId = ActivePlayers.Count;
    }

So everytime a player is added to the scene, you add it to your list. Since the list grows, so your playerID will also increment automatically. This way you don’t need to sort anything and the Id is more easy to retrieve

2 Likes

Hey, I did try something related to that, but my problem was that for some reason it wasn’t being transported to the player correctly. The only way I was able to garantee that it would work is if I loaded the players, assigned their Ids and then loaded the game world. I might try to implement this list of players since it will probably help me later on though.

I had a smiliar problem and solved it with the NetworkConnection class.
When you override OnServerAddPlayer (or OnClientConnect, etc…) you will have a NetworkConnection conn with it.
You can us the NetworkConnection class’ variable “connectionId” ( “Unique identifier for this connection that is assigned by the transport layer.” ) for having a unique id for every client. In my case i was assiging a unique prefab in the OnServerAddPlayer method with conn.connectionId.

Not sure if it’s the right way to do but it works so far for me.

Only problem that comes so far is that the host/server has the 0 and if you have on pc only acting as server and not as client at the same time he still occupies the 0.

I know its 6 years later but I wanted to thank you for this response! I swear I’ve spent the last 5 days stuck on this problem and couldn’t find an answer. You’re Godsend!

1 Like