Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Trying to send command for non-local player

Discussion in 'Multiplayer' started by teremy, Sep 4, 2015.

  1. teremy

    teremy

    Joined:
    May 2, 2015
    Posts:
    86
    Hello.

    I have worked myself into the new networking system, however I am having a problem, when I try to send a command, the console says: Tryin to send command for non-local player.
    Basically what I want todo is have a "Player" ( just one ) controlled by multiple people ( the clients ).
    I think the architecture of UNET won't allow me todo this, since ( this is my understanding, please correct me if I am wrong ) a Player is a reserved gameobject, that "represents" a client and only via ones own player object can one send a command to the server. So with 2 clients I also need 2 player objects, if both of them want to send commands, right?

    I also have a chat gameobject with a network identity and a script with the following code:
    Code (CSharp):
    1.  
    2.     [Command]
    3.     public void CmdSendMessage (string message)
    4.     {
    5.         RpcReceiveMessage (message);
    6.     }
    7.  
    8.     [ClientRpc]
    9.     void RpcReceiveMessage(string message)
    10.     {
    11.         AddMessage ("Unknown User", message);
    12.     }
    13.  
    I just want to send a message to the server, that uses that message as a parameter on a Rpc, so every client can add that message to the UI ( AddMessage(...) ).

    Can I even have scripts with commands, that are not placed on the player object?

    A client definitely needs to have a player gameobject in order to send commands, is this right? Then maybe I can just create the player gameobject without having it visible on screen, and the "player", that shall be controlled by the clients will be a different game object.

    Hope it's not too confusing, thanks for your time.


    Jan


    EDIT: Maybe just some more text. I don't really get why the player game object is the representation of the client ( I know there's also NetworkPlayer etc. ), what if a player dies and I destroy the object or what if it's a strategy game and a player controls many different units, that I want to tag as "Player"? Will there then be a hidden player game object ( just for sending the commands etc... ) ?
     
  2. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
  3. Firoball

    Firoball

    Joined:
    Aug 6, 2015
    Posts:
    60
    In that case I would have a "empty" gameobject for each player, handling all the input data and sending it via Commands.

    On the server I would spawn a regular gameobject.
    Then, add the logic to get all the data received by the client controlled objects and apply it to the server object.

    From there on, use SyncVars, ClientRPCs, NetworkTransform or custom implementation to get the "player" object synched properly on the clients in whatever way needed.
     
  4. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    This is where I'm stuck in. The server does not see the client's spawned object, even if I made the client to send a [Command] over to the server, telling the server to spawn in that client's spawned object in.
     
  5. Firoball

    Firoball

    Joined:
    Aug 6, 2015
    Posts:
    60
    This sounds like you're doing your own implementation without HLAPI?
    Otherwise you normally simply inherit from NetworkManager and override some event functions to adjust them to your needs.

    The Client should never spawn itself, it should only REQUEST a spawn.
    All the spawn work should be directed by the server - this makes the archtiecture clearer and is more secure (think of cheating).

    Client side - request player spawn:
    //dummy code if inheriting from NetworkManager
    OnClientConnect
    {
    ClientScene.Ready...
    //now request spawn
    ClientScene.AddPlayer...
    }

    Server side - catch request from client and trigger synchronized spawn:
    //dummy code if inheriting from NetworkManager
    OnServerAddPlayer
    {
    //create object instance
    GameObject player = GameObject.Instantiate...
    //now spawn it on all clients
    NetworkServer.AddPlayerForConnection...
    //now add code to add new player gameobject to some static list
    MyList.Add(player)
    }

    Some Server Spawned Object Script:
    //first add prefab of this gameobject to NetworkServer spawnable object list in editor
    GameObject obj = GameObject.Instantiate...
    NetworkServer.Spawn...

    Update routine
    //go through static list (InheritedNetworkManagerBehaviour.MyList)
    //get script with Command implementation for each client
    //grab any data you need
    //apply whatever needs to be done for each client to this single gameobject
     
  6. asperatology

    asperatology

    Joined:
    Mar 10, 2015
    Posts:
    981
    I did not know that. In fact, I did not know I have to inherit Network Manager to make it fit my needs. Thank you for your pseudo-code. It showed a whole door to me. Back to reading the docs, I guess.

    If any future questions regarding Network Manager and HLAPI implementation of RTS game modes, I will ask them in a different thread.
     
  7. teremy

    teremy

    Joined:
    May 2, 2015
    Posts:
    86
    Thanks for your answers.

    What I do now is I renamed my player to "Character", which is the game object, that shall be controlled by all the clients.
    I now have another gameobject Player, that checks for input etc. and sends commands, it has no visible representation in the game, it's just the gameobject used to send commands etc. now. Every client has its own player gameobject now ( auto created with the network manager ).
    This works so far, I have also noticed that there are mutliple player gameobjects ( one for each client ) and one can only send commands with the local player object, so I have to use "isLocalPlayer" in the function, that checks for user input.

    I also have implemented a chat, since commands can only be send by the (local) player object, I have to put these commands in the script, that is used by the player object, right?
    What I haven't tried yet, so should work I guess, is to delegate things to the local player object, so in my chat script ( that's not on the player game object ) I will have a reference to the local player game object and call methods its methods, which will then send commands.

    At least I think I have understood the architecture now, though I don't really know why there has to be multiple player game objects ( one for each client ) when only the local one is necessary to send commands, my guess is that they are needed for the RPCs, so each client has a corresponding player game object in the game of other clients.