Why isn't custom properties working correctly?

Hello guys,
I’m trying to make a multiplayer game similar to Ludo with PUN.

I would like that when starting the game, two players, RedPlayer and BluePlayer, were instantiated. I have already identified the two players using the PhotonNetwork.LocalPlayer.ActorNumber function. It’s going well. But the problem is when updating the positions of each Piece of the players in the OnPlayerPropertiesUpdate Method. I would like the RedPlayer Client to initialize its pieces in the initial position of the RedPlayer and the BluePlayer pieces, in the BluePlayer position and do the same in the BluePlayer Client.

It is not working, does anyone know why? Thanks

using Photon.Pun;
using Photon.Realtime;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Hashtable = ExitGames.Client.Photon.Hashtable;

public class GameController : MonoBehaviourPunCallbacks
{
    public ConnectController connectController;

    public int turnPlay;

    public GameObject[] tiles;
    public GameObject[] players;

    public Transform redTiles;
    public Transform blueTiles;

    public Transform redOutDices;
    public Transform blueOutDices;

    public GameObject playerPrefab;
    public GameObject playerCamera;

    public Material redMaterial;
    public Material yellowMaterial;
    public Material blueMaterial;
    public Material greenMaterial;

    [SerializeField]
    private Player redPlayer;
    [SerializeField]
    private Player bluePlayer;

    [SerializeField]
    private Text localPlayer;
    [SerializeField]
    private Text remotePlayer;

    public Hashtable playerCostumeProperties = new Hashtable();

    // Start is called before the first frame update
    void Start()
    {
        localPlayer.text = PhotonNetwork.LocalPlayer.ActorNumber.ToString();
        if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer.ActorNumber == 1)
        {
            PhotonNetwork.Instantiate(playerPrefab.name, playerPrefab.transform.position, playerPrefab.transform.rotation);
            GameObject playerClone = GameObject.Find("Player(Clone)");
            playerClone.name = "RedPlayer";
            playerClone.transform.GetChild(0).gameObject.SetActive(true);

            for (int i = 0; i < 4; i++)
            {
                players[i] = playerClone.transform.GetChild(i+ 1).gameObject;
                players[i].transform.GetChild(1).GetComponent<SkinnedMeshRenderer>().material = redMaterial;
            }
            for (int i = 0; i < 4; i++)
            {
                players[i].transform.position = redTiles.GetChild(2).GetChild(i).transform.position;
            }
            playerCostumeProperties.Add("RedPlayerName", "RedPlayer");
            playerCostumeProperties.Add("StartBluePlayersPos", true);
        }
        if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer.ActorNumber == 2)
        {
            PhotonNetwork.Instantiate(playerPrefab.name, playerPrefab.transform.position, blueOutDices.rotation);

            GameObject playerClone = GameObject.Find("Player(Clone)");
            playerClone.name = "BluePlayer";
            playerClone.transform.GetChild(0).gameObject.SetActive(true);

            for (int i = 0; i < 4; i++)
            {
                players[i] = playerClone.transform.GetChild(i + 1).gameObject;
                players[i].transform.GetChild(1).GetComponent<SkinnedMeshRenderer>().material = blueMaterial;
            }
            for (int i = 0; i < 4; i++)
            {
                players[i].transform.position = blueTiles.GetChild(2).GetChild(i).transform.position;
            }
            playerCostumeProperties.Add("BluePlayerName", "BluePlayer");
            playerCostumeProperties.Add("StartRedPlayersPos", true);
        }
        PhotonNetwork.LocalPlayer.SetCustomProperties(playerCostumeProperties);
    }

    public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
    {
        if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer.ActorNumber == 1)
        {
            foreach (Player player in PhotonNetwork.PlayerList)
            {
                if ((bool)player.CustomProperties.ContainsKey("BluePlayerName"))
                {
                    if ((string)player.CustomProperties["BluePlayerName"] == "BluePlayer")
                    {
                        GameObject bluePlayerClone = GameObject.Find("Player(Clone)");
                        if (bluePlayerClone == null)
                            return;

                        bluePlayerClone.name = "BluePlayer";
                    }
                }
                if ((bool)player.CustomProperties.ContainsKey("StartBluePlayersPos"))
                {
                    if ((bool)player.CustomProperties["StartBluePlayersPos"] == true)
                    {
                        GameObject bluePlayer = GameObject.Find("BluePlayer");
                        if (bluePlayer == null)
                            return;

                        for (int i = 0; i < 4; i++)
                        {
                            bluePlayer.transform.GetChild(i + 1).transform.position = blueTiles.GetChild(2).GetChild(i).transform.position;
                            bluePlayer.transform.GetChild(i + 1).transform.GetChild(1).GetComponent<SkinnedMeshRenderer>().material = blueMaterial;
                        }
                    }
                }
            }
        }
        if (PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer.ActorNumber == 2)
        {
            foreach (Player player in PhotonNetwork.PlayerList)
            {
                if ((bool)player.CustomProperties.ContainsKey("RedPlayerName"))
                {
                    if ((string)player.CustomProperties["RedPlayerName"] == "RedPlayer")
                    {
                        GameObject redPlayerClone = GameObject.Find("Player(Clone)");
                        if (redPlayerClone == null)
                            return;

                        redPlayerClone.name = "RedPlayer";
                    }
                }
                if ((bool)player.CustomProperties.ContainsKey("StartRedPlayersPos"))
                {
                    if ((bool)player.CustomProperties["StartRedPlayersPos"] == true)
                    {
                        GameObject redPlayer = GameObject.Find("RedPlayer");
                        if (redPlayer == null)
                            return;

                        for (int i = 0; i < 4; i++)
                        {
                            redPlayer.transform.GetChild(i + 1).transform.position = redTiles.GetChild(2).GetChild(i).transform.position;
                            redPlayer.transform.GetChild(i + 1).transform.GetChild(1).GetComponent<SkinnedMeshRenderer>().material = redMaterial;
                        }
                    }
                }
            }
        }
    }
}

Someone to help me?

First off: You need to be aware that players may leave a room (before the game started) and when another player joins, the actorNumbers are 2 and 3 (or any other combination with and without gaps).

PUN 2 has a PlayerNumbering script in the Utilities folder and this may help you sort players into Red and Blue or slot 1 and 2.

I would put the game state into the Custom Room Properties, instead of doing it per player. Yes, the pieces belong to players but the room properties are “complete”, no matter if the other player leaves or not.

When the player’s code knows which spot it has, it should be easy to move only pieces the player controls.

1 Like