Search code examples
c#unity-game-enginephoton

Enable & Disable Button On your Turn


I am trying to configure this type of game where I have 6 players connected to the same room. On game start, the Master Client (first player turn) starts where the UI button should be enabled only to him and it should be disabled to all other players and after the first player click the button it will get disabled and for the 2nd player alone it should be enabled and so on to all other players.

So i have this idea where a loop should iterate through the list of players when a button is clicked by the first or master client then getNext() that is the next player as per the actor number. The problem is how do i put in code? I was also recommended to use Custom properties but it has been a huge problem to me since i don't understand them. Watched some of the tutorials and also some documentation but I seem not to understand. I am currently not using photonview component.

let me just write a short code of what i mean;

    public class GameManager : MonoBehaviourPunCallbacks
    {
        private ExitGames.Client.Photon.Hashtable _myCustomProperties = new ExitGames.Client.Photon.Hashtable();

        private void Start()
        {
          //onstart the master client should only be the one t view the button and click it
          //his name should be displayed when it his turn

          if (PhotonNetwork.IsMasterClient)
          {
          Player_Name.text = PhotonNetwork.MasterClient.NickName + " " + "it's your turn";
          button.SetActive(true);
          }

        }

        //onclcik the Button
        public void TurnButton()
        {
            
            for(int i = 0; i<PhotonNetwork.Playerlist.length; i++)
             {
              //so every click of the button a loop should iterate and check the player if is the next to see the button and click it
             //a name should also be displayed on his turn as per his nickname

             }
        }

    }

Solution

  • There is no need for custom player properties here.

    I would rather use room properties for that

    public class GameManager : MonoBehaviourPunCallbacks
    {
        private const string ACTIVE_PLAYER_KEY = "ActivePlayer";
        private const string ACTIVE_ME_FORMAT = "{0}, you it's your turn!!";
        private const string ACTIVE_OTHER_FORMAT = "Please wait, it's {0}'s turn ...";
    
        private Room room;
    
        [SerializeField] private Button button;
        [SerializeField] private Text Player_Name;
    
        #region MonoBehaviourPunCallbacks
    
        private void Awake()
        {
            button.onClick.AddListener(TurnButton):
            button.gameObject.SetActive(false);
    
            Player_Name.text = "Connecting ...";
    
            // Store the current room
            room = PhotonNetwork.CurrentRoom;
    
            if (PhotonNetwork.IsMasterClient)
            {
                // As master go active since usually this means you are the first player in this room
    
                // Get your own ID
                var myId = PhotonNetwork.LocalPlayer.ActorNumber;
                // and se it to active
                SetActivePlayer(myId);
            }
            else
            {
                // Otherwise fetch the active player from the room properties
                OnRoomPropertiesUpdate(room.CustomProperties);
            }
        }
    
        // listen to changed room properties - this is always called if someone used "SetCustomProperties" for this room
        // This is basically the RECEIVER and counter part to SetActivePlayer below
        public override void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
        {
            // Maybe another property was changed but not the one we are interested in
            if(!propertiesThatChanged.TryGetValue(ACTIVE_PLAYER_KEY, out var newActiveID)) return;
    
            // if we got a value but it's not an int something is wrong in general
            if(!(newActiveID is int newActvieIDValue))
            {
                Debug.LogError("For some reason \"ACTIVE_PLAYER_KEY\" is not an int!?");
                return;
            }
    
            // otherwise apply the ID
            ApplyActivePlayer(newActvieIDValue);
        }
    
        // Optional but might be important (?)
        // In the rare case that the currently active player suddenly leaves for whatever reason
        // as the master client you might want to handle this and go to the next player then
        //public override void OnPlayerLeftRoom (Player otherPlayer) 
        //{
        //    if(!PhotonNetwork.IsMasterClient) return;
        //
        //    if(!propertiesThatChanged.TryGetValue(ACTIVE_PLAYER_KEY, out var currentActiveID) && currentActiveID is int currentActiveIDValue) return;
        //
        //    if(currentActiveIDValue != otherPlayer.ActorNumber) return;
        //
        //    var nextPlayer = Player.GetNextFor(currentActiveIDValue);
        //    var nextPlayerID = nextPlayer.ActorNumber;
        //    SetActivePlayer(nextPlayerID);
        //}
    
        #endregion MonoBehaviourPunCallbacks
    
        // Called via onClick
        private void TurnButton()
        {
            // this gets the next player after you sorted by the actor number (=> order they joined the room)
            // wraps around at the end
            var nextPlayer = Player.GetNext();
            // Get the id
            var nextPlayerID = nextPlayer.ActorNumber;
            // and tell everyone via the room properties that this is the new active player
            SetActivePlayer(nextPlayerID);
        }
    
        // This writes the new active player ID into the room properties
        // You can see this as kind of SENDER since the room properties will be updated for everyone
        private void SetActivePlayer(int id)
        {
            var hash = new ExitGames.Client.Photon.Hashtable();
            hash[ACTIVE_PLAYER_KEY] = id;
            room.SetCustomProperties(hash);
        }
    
        // this applies all local changes according to the active player
        private void ApplyActivePlayer(int id)
        {
            // get the according player
            var activePlayer = Player.Get(id);
    
            // Am I this player?
            var iAmActive = PhotonNetwork.LocalPlayer.ActorNumber == id;
    
            // Set the button active/inactive accordingly
            button.gameObject.SetActive(iAmActive);
    
            // Set the text accordingly
            Player_Name.text = string.Format(iAmActive ? ACTIVE_ME_FORMAT : ACTIVE_OTHER_FORMAT, activePlayer.NickName):
        }
    }