Changed object names and texture not send to later joined players

Options
Hello,

I recently started using PUN and I have encountered a problem I have not been able to solve (even through extensive google-fu).
Upon starting my application as MasterClient a list of cubes with a default texture is spawned as "Cube [Clone]", based on a location and name of already existing cubes in the scene (only used for location and name getting, deleted afterwards). Master automatically renames these as "Cube *indexNR*" and then sets textures accordingly upon initialisation.

However, if another player later connects, the cubes are still called "Cube [Clone]" and they have the default texture.

These are some snippets of my code:
if (PhotonNetwork.isMasterClient)
        {
            cubeStackFake.SetActive(true);
            cubeStackFake.GetComponent<Spawner>().initializeObjects();
        }
public void initializeObjects()
    {
        technovisionCubes = GameObject.FindGameObjectsWithTag("Technovision Cube");
        for (int i = 0; i < 44; i++)
        {
            Spawn(i);
        }
    }
public void Spawn(int i)
    {
        technovisionCubes[i].SetActive(false);
        object[] cubeData = new object[1];
        cubeData[0] = technovisionCubes[i].name;
        GameObject newCube = PhotonNetwork.InstantiateSceneObject(technovisionPrefab.name, technovisionCubes[i].transform.position, technovisionCubes[i].transform.rotation, 0, cubeData);
        newCube.name = technovisionCubes[i].name;
    }
The technovisionPrefab has an observed script likes this:
public class SetTexture : MonoBehaviour {

    private string name;

    void OnPhotonInstantiate(PhotonMessageInfo info)
    {
        if (PhotonNetwork.isMasterClient)
        {
            FindObjectOfType<Spawner>().Container.Add(this.gameObject);
            gameObject.name = gameObject.GetComponent<PhotonView>().instantiationData[0].ToString();
            name = gameObject.name;
            SetTextures(gameObject, int.Parse(System.Text.RegularExpressions.Regex.Match(gameObject.name, @"\d+").Value));
        }
    }

    private void SetTextures(GameObject technoCube, int i)
    {
        technoCube.transform.Find("Top").GetComponent<MeshRenderer>().material = Resources.Load("Materials/" + i + "_Top") as Material;
        technoCube.transform.Find("Bottom").GetComponent<MeshRenderer>().material = Resources.Load("Materials/" + i + "_Bottom") as Material;
        technoCube.transform.Find("Front").GetComponent<MeshRenderer>().material = Resources.Load("Materials/" + i + "_Front") as Material;
        technoCube.transform.Find("Back").GetComponent<MeshRenderer>().material = Resources.Load("Materials/" + i + "_Back") as Material;
        technoCube.transform.Find("Left").GetComponent<MeshRenderer>().material = Resources.Load("Materials/" + i + "_Left") as Material;
        technoCube.transform.Find("Right").GetComponent<MeshRenderer>().material = Resources.Load("Materials/" + i + "_Right") as Material;
    }

    void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
    {
        if (stream.isWriting)
        {
            Debug.Log("Sending info on box");
            stream.SendNext(name);
        }
        else
        {
            Debug.Log("Receiving info on box");
            name = stream.ReceiveNext().ToString();
        }
    }
}
But this doesn't work :( I've been stuck with this problem for around 8 hours now so I really hope someone here can help me!
I've also tried adding them to a public list, but the public list is different for each connected client..

Comments

  • Alexandra
    Alexandra
    edited August 2017
    Options
    It seems like OnPhotonSerializeView isn't called on the master client.
    So I get a nullreference exception in stream.ReceiveNext() on a connecting client.

    [EDIT: Ok so I found out that OnPhotonSerializeView only gets called when there are 2 or more players, but it still gets the nullreference]
  • Alexandra
    Options
    Is there anyone on this forum who can help me?
  • Hi @Alexandra,

    sorry for the late response.

    You currently only apply these changes for the local client, which is the MasterClient in this case. Those changes or modifications are unknown to other players, irrespective of they are already joined or joining afterwards. So you need to notify other clients as well. OnPhotonSerializeView might work in this case, but I wouldn't recommend using it here, because you only apply these modifications once.

    Since you instantiate those objects by using PhotonNetwork.InstantiateSceneObject, these objects also have an attached PhotonView component. This furthermore means, that you can use RPC calls on those objects and use them to inform other clients about this changes - even late joining clients. To do so, you can buffer those calls by setting the correct parameters. This might looks like the following:
    void OnPhotonInstantiate(PhotonMessageInfo info)
    {
        if (PhotonNetwork.isMasterClient)
        {
            GetComponent<PhotonView>().RPC("NotifyAboutModifications", PhotonTargets.AllBuffered, name, pathToLeftMat, pathToRightMat, etc); // maybe an array is the better option here
        }
    }
    
    [PunRPC]
    public void NotifyAboutModifications(string name, string pathToLeftMat, string pathToRightMat, object etc) // again think about using an array here
    {
        // add your logic here
    }
    If you have further questions, please feel free to ask.