There are multiple clients connected to a server (which is also a host)
For each of these clients, there is player object spawned by default by NetworkManager
Each of these clients requested another player object (with ClientScene.AddPlayer())
So there is 2N (N - client count) objects on each client spawned and each client owns two of them
Problem:
How can any client figure which two player objects are owned by another client?
What I found so far:
On server (who is client at the same time meaning itâs host), I can use NetworkIdentity.connectionToClient.playerControllers list which contains all spawned game objects owned by the client. However, all connection properties are null for all non-local player objects on all non-server clients.
My current solution is that server generates an id (a number) for each default player object and when another player object is spawned, it uses what I described above to find out all associated game objects in order to find the id and set it on synced variable.
This seems like something youâd wanna keep track of on the server, and just ask the server who controls what ya know. Like when a couple players join from one client, then have the server track that player x and player y are on client x, and then just ask the server from whichever player needs to know, whether player z is on client z and so on and so forth ya know? I guess that is easier said than done - but if you donât have players dropping out and joining in on the fly, it shouldnât be too hard to determine all of that in the lobby, and just have the server track whoâs who.
@manukanne Iâm afraid not. That checks which two of the objects are controller by local player (which is also important), but tells nothing about relations between all other instances.
@MD_Reptile Well, youâre totally right. However I guess I wasnât clear enough about how I use these player objects. These two player objects from single client represents single player, but for different purposes. My project works like this:
First all players connects to server and theyâre in lobby.
Default player objects are spawned - these objects represents players, but they have no visual representation (like 3D model). They are used to store various data about the player (name, id of selected character, whether theyâre ready to start main game, etc.) and other purpose is to actually communicate (because in new UNET hi-level api there is no other way to communicate with server other than spawning a player object - afaik)
After everything is ready, host starts the game. First, level is loaded, then all players send request to spawn their second player object.
Server knows which characters are selected by each client and spawns all requested player objects.
This player object is 3D/world representation of real player - itâs has 3d renderer, character controller etc.
And if I want to display something about the second player object, all clients usually need access to associated default player controller, because it contains some of the data. Of course, I could duplicate the data, but Iâm avoiding redundancy. (Very simple example: playerâs name.)
(Note: Iâm aware that Unity 5.2 brings non-player objects with client authority, but the feature is not out now, so Iâm using player objects instead.)
@MD_Reptile Thatâs ok. For now Iâm using an id generated by server, so itâs not real/bad blocker.
@manukanne Yup. One is for whole time a player is connected and contains basic info like name and provides communication. The other is spawned and despawned dynamically as players leave and enter lobby and contains info like how it looks like, animation, movement, etc.
You could send the Information to the Server with the first link. Then you have to creat MessaBase (second link). And on the Server side you have to create a handler (last link)
You are basically re-writing the NetworkLobbyManager. That is exaclty what it does. There is a NetworkLobbyPlayer that exists in the lobby, then it is replaced by the âGamePlayerâ when the âplay sceneâ is entered. The NetworkLobbyPlayer is DontDestroyOnLoad, and is made back into the connectionâs player object when returning to the lobby.
First, I apologize for such last reply - I didnât have time for the project and somehow lost track of this thread.
What you suggested is another way how to send the information from the server instead of clients finding out on their own. Even thought thatâs the way I solved the problem, itâs what I was trying to avoid. Anyway, thanks for the answer.
However, I found NetworkLobbyManager unusable - both for my personal project and for projects of company I work for. I find it extremely limiting and enforcing lots of things (or Iâm too dumb to use it properly). One example is changing scenes - there is no ânaturalâ way to allow some transition between scenes. Of course, I can override message handler for that and postpone the time when NetworkLobbyManager process the message. But thatâs a hack. Also, it doesnât (or didnât at the time) provide AsyncOperation so I couldnât display progress bar. Of course, I can override message handler for that and handle loading myself - but thatâs also a hack. There were multiple other problems and when I wrote about 4th or 5th hack, I was finally able to convince my leader to use NetworkManager instead. With our own lobby.
Anyway, I found the answer to the problem. Problem was âHow can any client figure which two player objects are owned by another client?â and the answer is: Clients doesnât have the information available, because only thing they have is connection to the server - nothing else. So if you want to detect which two network objects belong to single client, you must write your own code for sending/sharing such information from server, because otherwise, itâs simply not possible by design. One possible solution is what @manukanne suggested - see above. Another way is what I wrote earlier - server generates an ID and give it to all objects or share using sync vars. IDâs are equal for objects owned by same client.
My current solution is bit different. I spawn player object called âClientâ. Itâs a network behaviour representing a client with functionality associated with clients - for example lobby-ready state (âlobby-ready stateâ is actually clientâs state, not playerâs), client game state (loading scene, preparing scene, etc.) and others. There must be exactly one instance of this object per client.
Then there are players - there might be multiple players per client (for example for splitscreen). The player is initialized by server - server find out which client instance is client for given player and with RpcInitialize() method it sends this information to all clients.