Problem syncing a state across network

I have two players and I generate two random colors for each player. I want to sync that colors across the network to be able to see the respective players colors with each client.

So far my code is working but I’m sending a the colors through the network each FixedUpdate(). Obviously that’s not right and I want to send the colors of the player only once.

I’ve tryied to use OnStartClient() and onStartLocalPlayer() but without any luck.

Here you have the code I wrote. Can it be done more elegantly?

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

public class Player_ProceduralGeneration : NetworkBehaviour {

	[SerializeField] GameObject body;
	[SerializeField] GameObject arm;
	
	[SyncVar] Color syncBodyColor;
	[SyncVar] Color syncArmColor;
	
	Color randomBodyColor;
	Color randomArmColor;
	
	private MeshRenderer bodyRenderer;
	private MeshRenderer armRenderer;

	private Material bodyMaterial;
	private Material armMaterial;

	// Use this for initialization
	void Start () 
	{		
		// Generating random player colors
		randomBodyColor = new Color(Random.value, Random.value, Random.value);
		randomArmColor = new Color(Random.value, Random.value, Random.value);
	
		// Creating materials
		bodyMaterial = new Material(Shader.Find("Standard"));
		armMaterial = new Material(Shader.Find("Standard"));
		
		// Getting the object mesh 
		bodyRenderer = body.GetComponent<MeshRenderer>();
		armRenderer = arm.GetComponent<MeshRenderer>();
		
	}
	
	// FIXME: This should be applyed only when a player connects to the server.
	void FixedUpdate () 
	{
		SyncColors ();
		ApplyColors ();
	}

	void ApplyColors() 
	{
		// Assigning colors to materials
		bodyMaterial.color = syncBodyColor;
		armMaterial.color = syncArmColor;
		
		// assigning the new material to meshes
		bodyRenderer.material = bodyMaterial;
		armRenderer.material = armMaterial;
	}
	
	[Command]
	void CmdSendPlayerColorsToServer(Color bColor, Color aColor)
	{
		syncBodyColor = bColor;
		syncArmColor = aColor;
	}
	
	[Client]
	void SyncColors() 
	{	
		if (isLocalPlayer) {	
			CmdSendPlayerColorsToServer(randomBodyColor, randomArmColor);
		}
	}
	
}

Thanks for your help!

# EDIT 1

This is the result applying the changes proposed below in the comments. The players are the pink shapes, they have the body (capsule) and the arm (cube).

Another think I don’t understand is why the players are pink. They should be white, don’t we?

49131-colors1.png

Hello Lonthas !

SyncVar are automatically synced from the Server to the Client.
I think you shoud give authority to the server to sync colors :

 using UnityEngine;
 using UnityEngine.Networking;
 using System.Collections;
 
 public class Player_ProceduralGeneration : NetworkBehaviour {
 
     [SerializeField] GameObject body;
     [SerializeField] GameObject arm;
     
     [SyncVar] Color syncBodyColor = Color.white;
     [SyncVar] Color syncArmColor = Color.white;

     //You don't need that
     //Color randomBodyColor;
     //Color randomArmColor;
     
     private MeshRenderer bodyRenderer;
     private MeshRenderer armRenderer;
 
     private Material bodyMaterial;
     private Material armMaterial;
 
     // Use this for initialization
     void Start () 
     {        
         // Generating random player colors
         if (isLocalPlayer)
             CmdAskRandomColors();
     
         // Creating materials
         bodyMaterial = new Material(Shader.Find("Standard"));
         armMaterial = new Material(Shader.Find("Standard"));
         
         // Getting the object mesh 
         bodyRenderer = body.GetComponent<MeshRenderer>();
         armRenderer = arm.GetComponent<MeshRenderer>();
         
     }
     
     // FIXME: This should be applyed only when a player connects to the server.
     void FixedUpdate () 
     {
         //You don't need that anymore
         //SyncColors ();
         ApplyColors ();
     }
 
     void ApplyColors() 
     {
         // Assigning colors to materials
         bodyMaterial.color = syncBodyColor;
         armMaterial.color = syncArmColor;
         
         // assigning the new material to meshes
         bodyRenderer.material = bodyMaterial;
         armRenderer.material = armMaterial;
     }
     
     [Command]
     void CmdAskRandomColors()
     {
         syncBodyColor = new Color(Random.value, Random.value, Random.value);
         syncArmColor = new Color(Random.value, Random.value, Random.value);
     }       
 }

Or second version :

 [Command]
 void CmdSetColor(Color bodyColor, Color armColor)
 {
     syncBodyColor = bodyColor;
     syncArmColor = armColor;
 }