UNET copying material changes between localplayer and server instance

Hey guys,

Running into an interesting issue trying to allow customization of the playerPrefab. essentially I’m tryiing to allow the player to choose the ship color as well as engine colors. it works locally no problem, but because the array of renderer.materials needs to be replaced to correctly update the model, I need to find a way to serialize or build a struct to allow the array to be passed to the server. I’m worried that during this process I’ll have issues having particular prefabs of the ship updated, IE not every ship gets the color of the last update from any one player, merely every instance of that players ship gets the correct color value. This may or may not be an issue. Currently where I get stuck is trying to run the code as a Command in order to have the update occur on the server. I can’t use a SyncVar for an array. I’ve been digging in the logic of how syncliststructs work, and trying to get a better understanding of serialization, but so far am ending up more confused than really having any answers.

below is the code for my script which I was using to handle the colour change from gui. click the gui button and a particular int for index value is sent to update the array. This calls a seperate function to pass that array to the renderer.materials of that object. I was hoping someone might be able to help me understand how to pass this change to the player ship instance on the server, so that all clients will see the appropriate color values for the ship… Any help would be greatly appreciated.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;

public class MerauderMaterialSet : NetworkBehaviour {

	public Material[] shipBody;
	public Material[] driveTrain;
	[SerializeField]public Material[] existingMat;
	public Material[] standardMat;
	public int shipMaterial = 0;
	public int driveTrainMaterial = 1;
	public Renderer rend;
	public NetworkInstanceId thisNetworkObject;

	void Start() {
		rend = GetComponent<Renderer> ();
		rend.enabled = true;
	}

	void Update() {

		// assign it to the renderer
	}

	[Command]
	void CmdUpdateMaterials(int material1, int material2){
		existingMat = rend.materials;
		if (material1 != 99) {
			existingMat [0] = shipBody[material1];
		} else {
			existingMat [0] = existingMat [0]; 
		}
		if (material2 != 99) {
			existingMat [1] = driveTrain[material2];
		} else {
			existingMat [1] = existingMat [1];
		}
		rend.materials = existingMat;
	}

	public void ShipBodyAdjustment(int index){
		CmdUpdateMaterials (index, 99);
	}

	public void DriveTrainAdjustment(int index){
		CmdUpdateMaterials (99, index);
	}
}

Is it possible to create a command function at the tail of UpdateMaterial, to simply pass the renderer settings? I’m not sure what would make the most sense or how to format the data being sent.

Okay so actually I figured this out. If you watch the battle tanks live training from unity. They use a hook with a simple sync var to pass the color to the existing material. They only do it on the root material. I realized that a simpler method than what I was trying to do above was to in the start function build an array and pass the contents of renderer.materials to it. Within that array I choose the index of the two materials that I wanted to change and individiually update the color of those materials. Once done, I simply apply the array back to renderer.materials.

The live training has all the hook and sync var pieces so I won’t add that, but here is the code I used (realy Simple) to update the colors on the gameObject.

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

public class ShipPlayerDetails : NetworkBehaviour {

	[SyncVar]
	public Color color;
	[SyncVar]
	public Color driveColor;
	[SyncVar]
	public string playerName;
	public TextMesh pname;
	private Material[] newMat;

	private MeshRenderer rends;

	void Start(){
		rends = gameObject.GetComponent<MeshRenderer> ();
		//rends.material.color = color; 
		newMat = rends.materials;
		newMat [0].color = color;
		newMat [1].color = driveColor;
		rends.materials = newMat;
		pname.text = playerName;
	}
}

This doesn’t solve the question of how to do this in real time during gamePlay, but I’m sure a similar configuration would work, utilizing the sync vars.