Command not being called on client

So the player move command isn’t being called. The loop is being called and I checked that it is only on the local player. But the actual command isn’t being called. The script is on the player prefab which is registered in the network manager. What am I doing wrong?

using UnityEngine;
using UnityEngine.Networking;

public class MovePlayer : NetworkBehaviour {
    float speed;
    Rigidbody2D rigidbody;
    Player player;
    int verticalDir = 0;
    float rot_z;
    int horizontalDir = 0;

    void Start () {
        player = gameObject.GetComponent<Player>();
        rigidbody = gameObject.GetComponent<Rigidbody2D>();
        speed = player.moveSpeed;
    }

	void Update () {
        if (!player.dead && isLocalPlayer)
        {
            // Key Movement
            verticalDir = 0;
            horizontalDir = 0;
            if (Input.GetKey("w"))
            {
                verticalDir += 1;
            }
            if (Input.GetKey("s"))
            {
                verticalDir -= 1;
            }
            if (Input.GetKey("a"))
            {
                horizontalDir -= 1;
            }
            if (Input.GetKey("d"))
            {
                horizontalDir += 1;
            }

            // Mouse Tracking
            Vector3 diff = player.camera.ScreenToWorldPoint(Input.mousePosition) - transform.position;
            diff.Normalize();

            rot_z = Mathf.Atan2(diff.y, diff.x) * Mathf.Rad2Deg;
            CmdMove();

            // Velocity limit
            if (rigidbody.velocity.x > speed)
            {
                rigidbody.velocity = new Vector2(speed, rigidbody.velocity.y);
            }
            if (rigidbody.velocity.y > speed)
            {
                rigidbody.velocity = new Vector2(rigidbody.velocity.x, speed);
            }
        }
    }
    [Command]
    void CmdMove()
    {
        var locVel = new Vector2(speed * horizontalDir, speed * verticalDir);
        rigidbody.velocity = locVel;
        gameObject.transform.rotation = Quaternion.Euler(0f, 0f, rot_z - 90);
    }
}

It’s quite likely that the command is being called, but you don’t actually see it since none of the data you modify in it actually gets sent to the clients. Commands are called on the server, and so the server’s version of the object had these values changed, but the clients never saw it. What’s needed is a SyncVar or a ClientRPC. RPCs are called on the client, and can be called in a command function. This causes the Rpc function to be called on every client. What you need is something along the lines of:

[Command]
void CmdMove(Vector2 movedir, float rotz)
{
     RpcMove(movedir, rotz);
}

[ClientRPC]
void RpcMove(Vector2 movedir, float rotz){
     var locVel = movedir*speed;
     rigidbody.velocity = locVel;
     gameObject.transform.rotation = Quaternion.Euler(0f, 0f, rotz - 90);
}

(Code above is untested, but the general idea is that you need to be calling an RPC).

Note 2 things about the above code

  • The Command tells the server to call the RPC on all the clients
  • The movement vectors are passed in as parameters. The movement vector isn’t synchronized and is only accurate on the client doing the moving. For all other clients and for the server this is zero, so we need to tell the server what our move vector is.

Alternately, the [SyncVar] attribute causes a variable to get sent to all clients whenever it is changed on the server, so the RPC step gets done for you.

Always remember that [Command], [ClientRPC], [TargetRPC], and [SyncVar] are just ways of hiding the messages that are being sent internally, and none of the other clients will know what your client knows until you tell the server and the server tells them.