Search code examples
unity-game-enginenetworkingrpcunity3d-unetunity-networking

Unity Unet Adjusting a syncvar from a player action? - What am i doing wrong?


I'm attempting something that should be pretty simple, as it should happen in gaming quite often. I'm allowing players to spawn cubes in the world, and then when a player clicks on a cube, the cube's text value (and associated syncvar counter) are changed.

However, this ONLY works when attempting this from the server/client combination. What am i doing wrong? I'm blown away by not being able to find tutorials on this as its something that seems to be ubiquitous in games.

SpawnCube.cs (attached to each player)

 if (Input.GetKeyDown (KeyCode.Mouse1)) {
            RaycastHit hit;
            if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 1000f, layers)) {

                SpawnedCubeController scc = hit.collider.gameObject.GetComponent<SpawnedCubeController>();
                if (scc != null) {
                    print ("HIT A CUBE");
                    scc.CmdAdjustCounter (1);
                } else {
                    Vector3 hitPos = new Vector3(hit.point.x, hit.point.y + .5f, hit.point.z);

                    Quaternion look = Quaternion.LookRotation(hitPos - this.transform.position);
                    CmdSpawnCube(hitPos, look);
                }


            }
        }

And then the meat is in the SpawnedCubeController.cs, which is attached to the spawned cube.

public class SpawnedCubeController : NetworkBehaviour {

[SyncVar(hook = "OnChangeCounter")]
public int counter = 10;
private TextMeshProUGUI text;

public void OnChangeCounter(int newCount) {
    if (text == null)
        text = gameObject.GetComponentInChildren<TextMeshProUGUI> ();

    text.text = "" + newCount;
}

[Command]
public void CmdAdjustCounter(int amount) {
    this.counter -= amount;

    if (this.counter <= 0) {
        Destroy (this.gameObject);
    }

    if (isServer) 
        RpcUpdateCounter (counter);
}

[ClientRpc]
public void RpcUpdateCounter (int amount) {
    text.SetText ("" + amount);
}

In my example, everyone can spawn and rotate the cubes just fine - however i can't for the life of me get everyone to be able to execute the command.

I dont even think the RpcUpdateCounter is necessary, as the hook should manage this? Regardless, clicking on a cube on any machine other than the server will never run the command

Thanks!


Solution

  • The problem here is that you are trying to execute a Command from an object without authority (I'm pretty sure that if you check your console logs on the client, the warning will appear when you fire the command).

    The only objects on your scene that have authority by default are your player gameObjects, so the command function should be on them.

    The other way to do that is to give authority to the cubes before do the command, and take it over when they finished the action.

    Give authority to non-player objects: https://unity3d.com/es/learn/tutorials/topics/multiplayer-networking/handling-non-player-objects