Search Unity

How can I find out which player objects are owned by same client in another client?

Discussion in 'Multiplayer' started by Inaetaru, Aug 25, 2015.

  1. Inaetaru

    Inaetaru

    Joined:
    Aug 9, 2015
    Posts:
    16
    Situation:
    • 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.
     
  2. manukanne

    manukanne

    Joined:
    Jul 17, 2015
    Posts:
    8
    You could check it with "isLocalPlayer"
     
  3. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    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.
     
  4. Inaetaru

    Inaetaru

    Joined:
    Aug 9, 2015
    Posts:
    16
    @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.)
     
  5. MD_Reptile

    MD_Reptile

    Joined:
    Jan 19, 2012
    Posts:
    2,664
    Dang, yeah I see what your saying. Yeah that's a bit more complicated. Wish I could come up with some more advice, but I'm drawing a blank haha.

    Good luck!
     
  6. manukanne

    manukanne

    Joined:
    Jul 17, 2015
    Posts:
    8
    So each Player instance hold several Information which you want to share with the other Clients?
     
  7. Inaetaru

    Inaetaru

    Joined:
    Aug 9, 2015
    Posts:
    16
    @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.
     
  8. manukanne

    manukanne

    Joined:
    Jul 17, 2015
    Posts:
    8
  9. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    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.
     
  10. Inaetaru

    Inaetaru

    Joined:
    Aug 9, 2015
    Posts:
    16
    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.
     
    GaryMooney likes this.