Managing variables over Multiplayer Networking (UNET)

Okay… I’m spending days to understand how to do some simple things.

I’m simplifying my situation in a way that you guys can understand what’s my problem.

I have a cube which changes the color with a right mouse click or a left click on a button.
The simple click works on both host and client, the button works on the host, it doesn’t on the client.

playerLogics.cs

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class playerLogics : NetworkBehaviour
{

    [SyncVar]
    private Color syncColor;

    public GameObject targetObj; // This is the cube.

    void Start()
    {
        targetObj = GameObject.Find("Target"); // The cube is called "Target"
    }

    void Update()
    {
        targetObj.GetComponent<Renderer>().material.color = Color.Lerp(targetObj.GetComponent<Renderer>().material.color, syncColor, Time.deltaTime * 4); // Lerping the color just because it's nicer ;)
        if (Input.GetButtonDown("Fire2"))
            ToTheClient();
    }

    [Command]
    public void CmdToTheServer(Color color)
    {
        syncColor = color;
    }

    [ClientCallback]
    public void ToTheClient()
    {
        CmdToTheServer(new Color(Random.Range(0.0f, 1), Random.Range(0.0f, 1), Random.Range(0.0f, 1), 1));
    }
}

buttonLogics.cs

using UnityEngine;
using System.Collections;

public class buttonLogics : MonoBehaviour {

    public GameObject thePlayer;

    void Update()
    {
        if(!thePlayer)
        thePlayer = GameObject.FindGameObjectWithTag("Player");
    }
    public void callThePlayer()
    {
        thePlayer.GetComponent<playerLogics>().ToTheClient();
    }
}

I tried a lot, but I can’t fully understand. Giving the button a network identity and turning it in a NetworkBehaviour didn’t help.
And I have this kind of problem on a larger scale in a project I’m working on at the moment.

Reference on how to manage variables on UNET are still quite scarce…
Or maybe it’s just me. =)

Edit:
Oh sorry, I’ve edited this so much that it almost lost the connection with the title. But still, all my trouble is about making player and other objects talk over UNET about their variables :smile:

Your close to the answer but get rid of your ToTheClient() method and change where you originally called that method to CmdToTheServer(newColor(Random.Range(0.0f, 1), Random.Range(0.0f, 1), Random.Range(0.0f, 1), 1)); then add a new method called

[ClientRpc]
RpcToTheClient(Color newColor){
color = newColor;
}

Thanks, but I don’t quite understand where to call this new method from and how to link everything together with the button. I tried to call the RpcToTheClient from the button or from the CmdToTheServer to no avail.
The logic escapes me.

[Command]s can be called by a local player script (a script attached to the PlayerPrefab, spawned by the NetworkManager), and run on the same object on the server. [ClientRpc]s can be called from any NetworkBehaviour-derived script on the server and will be called on the same object on all clients.

If you want a button press to fire everywhere, you should call a [Command] function (which runs on the server) from the local player script that sets the syncvar.

Thanks Adriaan,
it’s getting clearer, I made it work. The thing, amongst the others, was to make the button point to the correct instance of the player prefab, hence use an if(isLocalPlayer) to name it specifically to be found by the button.
Now I’m not using RPCs at all and the codes look like this:

playerLogics.cs

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class playerLogics : NetworkBehaviour
{

    [SyncVar]
    public Color syncColor;

    public GameObject targetObj;

    void Start()
    {
        if (isLocalPlayer)
            transform.name = "Player";

        targetObj = GameObject.Find("Target");
    }

    void Update()
    {
        targetObj.GetComponent<Renderer>().material.color = Color.Lerp(targetObj.GetComponent<Renderer>().material.color, syncColor, Time.deltaTime * 4);
        if (Input.GetButtonDown("Fire2"))
        {
            CmdToTheServer(new Color(Random.Range(0.0f, 1), Random.Range(0.0f, 1), Random.Range(0.0f, 1), 1));

        }
    }

    [Command]
    public void CmdToTheServer(Color color)
    {
        syncColor = color;
    }
}

buttonLogics.cs

using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class buttonLogics : NetworkBehaviour {

    public GameObject thePlayer;

    void Update()
    {
        if (!thePlayer)
            thePlayer = GameObject.Find("Player");
          
    }
    public void callThePlayer()
    {
        thePlayer.GetComponent<playerLogics>().CmdToTheServer(new Color(Random.Range(0.0f, 1), Random.Range(0.0f, 1), Random.Range(0.0f, 1), 1));
    }
}

Does it make sense? Is it “the best” way around it?
Because now I have to bring this logic back to my real project and see if my new knowledge holds :smile:
Thanks again anyway.