Photon实现点击I am Ready按钮时就绪玩家统计异常问题咨询
问题根因分析
你当前代码的核心逻辑错误是混淆了玩家个人状态存储和全局就绪人数统计的边界:
PhotonNetwork.LocalPlayer.CustomProperties是每个玩家独立持有的自定义属性集合,你现在把累加的就绪人数存在每个玩家自己的属性里,相当于每个客户端各自维护自己的计数,完全无法同步全局的就绪总人数。- 你没有监听全房间玩家的属性变更事件,其他玩家点击就绪按钮后,本地客户端无法收到通知,自然也没法更新统计值。
修复方案
第一步:调整自定义属性逻辑
每个玩家的自定义属性仅存储自身是否就绪的布尔值,全局就绪人数由所有客户端遍历全量玩家列表统一统计。
第二步:补充属性变更监听
实现Photon的回调接口,监听玩家属性变更事件,每次有玩家更新就绪状态时自动重新统计全局人数。
修复后参考代码
using UnityEngine; using Photon.Pun; using Photon.Realtime; using Hashtable = ExitGames.Client.Photon.Hashtable; public class ReadyRoomManager : MonoBehaviourPunCallbacks { // 就绪按钮引用 public GameObject IamReadyButton; // 全局就绪人数缓存 private int ReadyPlayers = 0; private void Start() { // 初始化本地玩家的就绪状态为未就绪,避免取值报错 if (PhotonNetwork.LocalPlayer.CustomProperties["PlayerReady"] == null) { Hashtable initHash = new Hashtable() { { "PlayerReady", false } }; PhotonNetwork.LocalPlayer.SetCustomProperties(initHash); } } // 按钮点击事件 public void OnClickIamReady() { // 仅更新本地玩家自己的就绪状态为true Hashtable hash = new Hashtable() { { "PlayerReady", true } }; PhotonNetwork.LocalPlayer.SetCustomProperties(hash); IamReadyButton.SetActive(false); } // 监听玩家自定义属性变更回调,全房间玩家的属性变更都会触发这个方法 public override void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) { if (!changedProps.ContainsKey("PlayerReady")) return; // 每次属性变更时重新统计全量就绪玩家数 ReadyPlayers = 0; foreach (Player player in PhotonNetwork.PlayerList) { if (player.CustomProperties.TryGetValue("PlayerReady", out object isReadyObj) && (bool)isReadyObj) { ReadyPlayers++; Debug.Log($"{player.NickName} 已就绪,当前就绪总人数:{ReadyPlayers}"); } } // 仅由房主触发开局逻辑,避免多客户端重复触发 if (PhotonNetwork.IsMasterClient && ReadyPlayers == PhotonNetwork.PlayerList.Length) { Debug.Log("所有玩家已就绪,开始开局倒计时"); // 这里调用你的倒计时启动逻辑 StartCountDown(); } } private void StartCountDown() { // 你的倒计时实现逻辑 } }
额外注意事项
- 如果允许玩家取消就绪,可以在点击按钮时做状态切换,把
PlayerReady设为false后重新统计即可。 - 玩家退出房间时会自动触发
OnPlayerLeftRoom回调,建议在这个回调里也加一次就绪人数统计逻辑,避免有玩家就绪后退出房间,统计值不准。
内容的提问来源于stack exchange,提问作者Shem Tom
相关产品推荐
相关产品推荐

