[PUN2] Late joining players don't see any changes made in the scene

I am trying to build a simple FPS multiplayer game using Photon PUN 2. In my game, there are some targets, and players can raycast at them to change their color. I am using RPC with RpcTarget.AllBuffered. Everything gets synchronized well if players join in the room first and then start shooting at targets. Unfortunately, late joining players in the room don’t see any changes made so far by other players.

In my code, I used:
PhotonNetwork.AutomaticallySyncScene = true;
PhotonNetwork.LoadLevel(1);

Any help to fix this issue would be much appreciated. Thanks in advanced.

My guess would be that your only changing it for the current players in the room, so people who join late won’t receive the RPC

Yeah, you might be right. I was wondering how to send RPC for both current and late joining players? Any sample code ?

RPC’s that arent buffered for all will be lost. Thats all that is happening. You need to ensure they all recieve those packets if it matters.

I am already using RpcTarget.AllBuffered. This is not working for the late joining players. What are other options to make buffered RPC?

Maybe try AllBufferedViaServer, not really sure on this one

I tested AllBufferedViaServer too. But not working in my case.

Maybe for the players who join late, send the RPC to them when they join?

That might be a way out. I will try to implement that and post update here. Thanks!!

I have solved it using photon custom properties. When I am changing the color of a target using raycasting, I am storing its photonViewId and color value in a Hashtable. Late-joining players use this Hashtable in OnJoinedRoom() callback to synchronize all changes in that room.

Here is my sample code:

step 01: while creating a new room, initialize the room’s custom properties

private void CreateNewRoom()
{
    int randomRoomNumber = 100;
    RoomOptions roomOptions =
    new RoomOptions()
    {
        IsVisible = true,
        IsOpen = true,
        MaxPlayers = 5,
    };

    Hashtable roomHT = new Hashtable();
    string photonViewid = "0";
    roomHT.Add(photonViewid, new Vector3(0, 0, 0)); // key should be a string
    roomOptions.CustomRoomProperties = roomHT;

    PhotonNetwork.CreateRoom("RoomName_" + randomRoomNumber, roomOptions);
}

step02: store target’s photonViewId and color value in the hashtable during rpc

[PunRPC]
void ShootRPC()
{
    particalSys.Play();
    Ray ray = new Ray(gunTransform.position, gunTransform.forward);
    LayerMask mask = LayerMask.GetMask("targets");

    if (Physics.Raycast(ray, out RaycastHit hit, 100f, mask))
    {
        raycastGO = hit.collider.gameObject;

        var enemyHealth = gameManager.GetComponent<ScoreBoard>();
        var menuManager = gameManager.GetComponent<MenuManager>();

        if (enemyHealth && menuManager)
        {          

            if (menuManager.command == "red")
            {
                raycastGO.GetComponent<MeshRenderer>().material = red;

                int photonViewId = raycastGO.GetComponent<PhotonView>().ViewID;
                Vector3 color = new Vector3(241, 19, 19);
                PhotonNetwork.CurrentRoom.SetCustomProperties
                (new Hashtable() { { photonViewId.ToString(), color } });
            }

            if (menuManager.command == "green")
            {
                raycastGO.GetComponent<MeshRenderer>().material = green;

                int photonViewId = raycastGO.GetComponent<PhotonView>().ViewID;
                Vector3 color = new Vector3(20, 91, 17);
                PhotonNetwork.CurrentRoom.SetCustomProperties
                (new Hashtable() { { photonViewId.ToString(), color } });
            }           
        }
    }
}

step03: when a new player joins, use that Hashtable in OnJoinedRoom() callback to synchronize all changes

public override void OnJoinedRoom()
{
    Hashtable customProperties = PhotonNetwork.CurrentRoom.CustomProperties;

    foreach (string key in customProperties.Keys)
    {
        if (key.Contains("0") || key.Contains("curScn"))
        {
            //do nothing
        }
        else
        {
            int photonViewID = int.Parse(key);

            PhotonView photonView = PhotonView.Find(photonViewID);

            GameObject gameObject = null;
            if (photonView != null)
            {
                gameObject = photonView.gameObject;
            }

            var colorInfo = (Vector3)customProperties[key];
            float r = colorInfo.x / 255;
            float g = colorInfo.y / 255;
            float b = colorInfo.z / 255;

            if (gameObject != null)
            {
                gameObject.GetComponent<MeshRenderer>().material.color
                = new Color(r, g, b);
           
            }
        }
    }
}