The question is answered, right answer was accepted.
How to sync color with other players (Unet)
When a player is created he gets a random color, then I want all other players to sync with his color.
I can't get the network to sync the players colors! Either only one gets synced, no one gets synced or every player sees a random color on every player.
How do I sync the color between all player?
I have only tested around to try and understand, this one currently gets one synced but not the other ones ?
[Command]
void CmdSetColor(){
Color myColor = new Color (Random.Range (0.0f, 1.0f), Random.Range (0.0f, 1.0f), Random.Range (0.0f, 1.0f));
RpcSetColor(myColor);
}
[ClientRpc]
void RpcSetColor(Color col){
GetComponent<Renderer> ().material.color = col;
}
I call the CmdSetColor() in the start method if I am the local player
void Start(){ if(netId.Value==1) GetComponent ().material.color = Color.blue; if(netId.Value==2) GetComponent ().material.color = Color.red; if(netId.Value==3) GetComponent ().material.color = Color.green; //etc... }
void Start(){ if(netId.Value==1) GetComponent<$$anonymous$$eshRenderer> ().material.color = Color.blue; if(netId.Value==2) GetComponent<$$anonymous$$eshRenderer> ().material.color = Color.red; if(netId.Value==3) GetComponent<$$anonymous$$eshRenderer> ().material.color = Color.green; //etc... }
Answer by HueHue44 · Oct 18, 2015 at 06:06 PM
I solved it myself, if anyone else is having trouble with this here it is
[SyncVar]private Color randomColor;
void Start(){
if(isLocalPlayer){
randomColor = new Color (Random.Range (0.0f, 1.0f), Random.Range (0.0f, 1.0f), Random.Range (0.0f, 1.0f));
GetComponentInChildren<Renderer>().material.color = randomColor;
}
}
[Command]
void Cmd_ProvideColorToServer(Color c){
randomColor = c;
}
[ClientCallback]
void TransmitColor(){
if(isLocalPlayer){
Cmd_ProvideColorToServer(randomColor);
}
}
public override void OnStartClient ()
{
StartCoroutine (UpdateColor (1.5f));
}
IEnumerator UpdateColor(float time){
float timer = time;
while (timer > 0) {
timer -= Time.deltaTime;
TransmitColor ();
if(!isLocalPlayer)
GetComponentInChildren<Renderer>().material.color = randomColor;
yield return null;
}
}
I really feel like this isn't the best way to do it, I just kind of guessed away and eventually got the results I wanted. I only update the color for a short time after OnStartClient() because the color wont update if I just run it once in the OnStartClient() for some reason. Even though this works for me I would like to get some tips on how to improve this!
Hi, thanks for putting this up! i have just started working with both UNet, and multiplayer in general as part of my uni studies, and this has had me stumped for the better part of a week. One thing however, the result i am recieving is making the local player always black, yet for everyone else, the same color. eg, with 3 people, on the players screen, they are black, yet for the other two people, you are (for example) purple. Any ideas? (sorry to reopen, i saw this was only said to be "done" 10 days ago.)
If you're still interested, I made an implementation that looks a bit like yours. It's a little bit cleaner and relies on the server to pick the color ins$$anonymous$$d of the Local Player instance. The Server then outputs this color to the other clients:
public class NetworkRandomColor : NetworkBehaviour {
// This list can be filled from the editor with multiple renderers in a prefab
public List<Skinned$$anonymous$$eshRenderer> $$anonymous$$eshes = new List<Skinned$$anonymous$$eshRenderer>();
[SyncVar]
public Color m_color;
void Start()
{
if ( isLocalPlayer)
{
foreach (Skinned$$anonymous$$eshRenderer mesh in $$anonymous$$eshes)
{
mesh.material.color = m_color;
}
CmdSet$$anonymous$$eshColors(m_color);
}
else
{
CmdSet$$anonymous$$eshColors(m_color);
foreach (Skinned$$anonymous$$eshRenderer mesh in $$anonymous$$eshes)
{
mesh.material.color = m_color;
}
}
}
public override void OnStartClient()
{
if (isServer)
{
m_color = new Color(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f));
RpcSetColor(m_color);
}
}
[ClientRpc]
void RpcSetColor( Color c )
{
m_color = c;
foreach (Skinned$$anonymous$$eshRenderer mesh in $$anonymous$$eshes)
{
mesh.material.color = m_color;
}
}
//Server Commands
[Command]
public void CmdSet$$anonymous$$eshColors(Color c)
{
m_color = c;
}
}
Thank you so much!! After testing thousands of ways, this is what I find the best and most understandable solution. God bless you
I had a similar problem, and have a solution simpler than the ones that have been posted already. I wanted to share it in case it's helpful for someone (it's for 2D but could be changed to 3D fairly easily):
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
/// <summary>
/// Assigns a random color to this sprite when it is created.
/// </summary>
public class RandomizeColor : NetworkBehaviour {
/// <summary>
/// The chosen color.
/// </summary>
[SyncVar]
private Color chosenColor;
void Start() {
SetColor(chosenColor);
}
public override void OnStartClient() {
if (isServer) {
chosenColor = ChooseColor();
}
}
/// <summary>
/// Returns a random color.
/// </summary>
/// <returns>A random color.</returns>
private Color ChooseColor() {
// create a list of colors
List<Color> colors = new List<Color> { Color.blue, Color.cyan, Color.green, Color.magenta, Color.red, Color.white, Color.yellow };
// get a random color
return colors[Random.Range(0, colors.Count)];
}
/// <summary>
/// Sets the color of this sprite to the provided color.
/// </summary>
/// <param name="color">The color to set.</param>
private void SetColor(Color color) {
GetComponent<SpriteRenderer>().material.color = color;
}
}
maybe i am a bid late but your code only work if you are the host do you know how i can fix that?
void Start(){ if(netId.Value==1) GetComponent ().material.color = Color.blue; if(netId.Value==2) GetComponent ().material.color = Color.red; if(netId.Value==3) GetComponent ().material.color = Color.green; //etc... }