Search Unity

Cmd vs if (!isServer)

Discussion in 'Multiplayer' started by hottabych, Jul 3, 2018.

  1. hottabych

    hottabych

    Joined:
    Apr 18, 2015
    Posts:
    107
    What's a difference if I use Command to run code on the server, or if I simply run the method and use an `if (!isServer) return` construction or [Server] attribute? Result should be the same: it tries to run the code on all copies of a gameobject and does it on server only.
    There are both ways used in Simple Multiplayer tutorial in the Learn section. Cmd for bullet spawning and isServer check for TakeDamage.
     
  2. Ellernate

    Ellernate

    Joined:
    Aug 25, 2017
    Posts:
    81
    Command is used by a non-authority to directly send something to whoever has authority over the object (usually server). It's used in bullet spawning because that is the most logical way to communicate the intentions of the client. I'm curious to know how you do bullet spawning without using command or messages
     
  3. hottabych

    hottabych

    Joined:
    Apr 18, 2015
    Posts:
    107
    Well, why TakeDamage does not use Command in the tutorial? It's a logical way too, to send Cmd to server and ask it to change the player's health.
     
  4. hottabych

    hottabych

    Joined:
    Apr 18, 2015
    Posts:
    107
    I think you understand something wrong. Only Player or object with Client Authority can send commands (always from client to server).
     
  5. Ellernate

    Ellernate

    Joined:
    Aug 25, 2017
    Posts:
    81
    Ah, you're correct. I follow a strict client-server model so I sometimes overlook the local player authority stuff. I meant authority as in the server
     
  6. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,556
    There's a subtle difference when these flags contain what value. As people pointed out above, each player objects has their own representation on the server. For all these copies, their (isServer) flag is true, while for most (even all) the hasAuthority flag is false. Even more confusing can be the fact that if you are self-hosting a game: in that case one player object will have isServer, isClient, and hasAuthority all set to true.

    But underlying all this is the issue of usage: with (isServer) you test the state of the script that is currently executing. With Commands, you force a particular piece of code (the Cmd) to be executed on the server (i.e. on a different machine). This is done by sending a request ACROSS THE NETWORK -- using a Cmd usually causes a network request sent from the currently local player object (or object with authority) running on a client, to the server to execute that command on the server's copy of the object. So, Cmd causes a Network operation to be sent to the server, while testing (isServer) merely checks the flow of your code on a particular machine (any Client or the Server).

    The Command stuff usually comes in when you need to spawn or destroy objects, i.e. do something that can only be done on the Server, but is detected by a client (e.g. user input). Only on self-hosted games (where one player also hosts the game) will you have the situation that code using (isServer) can result in the same as Cmd, and only for the player that hosts the game. For all other local Players this will fail, as their code is executed on a different machine/process.
    If they use Cmd instead, this request is sent over the net to the server, and then executed on the instance of that player on the server (that is also why there is no return values for Cmd - they run asynchronously, and when they fail, your Client will not be informed). Since a Cmd is usually a result of some Input/local event (e.g. keypress), tthe server copy of your instance doesn't know about it, and so you can't program for it by using an (isServer) guard.

    Hopefully this sheds some light into this definitely complex issue.

    -ch
     
    hottabych likes this.