房主离开Photon房间触发setProperties异常的解决方法咨询
问题解决:房主离开时SetCustomProperties触发日志异常
问题现象
将房间时长计时器设为房间属性后,房主离开房间时会触发日志异常:
Operation setProperties (252) not called because client is not connected or not ready yet, client state: Leaving
该错误不影响功能运行,但会干扰日志输出,其他玩家退出时无此问题。引发问题的核心代码如下:
private void Update() { _currentPlayersCountText.text = PhotonNetwork.PlayerList.Length.ToString(); if (PhotonNetwork.IsMasterClient) { if (PhotonNetwork.PlayerList.Length >= 5) { _startGameButton.GetComponent<Button>().enabled = true; } else { _startGameButton.GetComponent<Button>().enabled = false; } Hashtable ht = PhotonNetwork.CurrentRoom.CustomProperties; ht.Remove("timer"); ht.Add("timer", _roomTimer.timeRemaining); PhotonNetwork.CurrentRoom.SetCustomProperties(ht); } if (_roomTimer.timeRemaining <= 110) { LeaveRoom(); } }
问题原因
房主执行LeaveRoom()后,客户端进入Leaving状态,但Update循环不会立即终止。此时PhotonNetwork.IsMasterClient仍可能返回true,代码会继续尝试调用SetCustomProperties,但客户端已处于断开连接的过程中,因此触发日志异常。
解决方案
1. 添加离开标记,阻止后续属性更新
在类中添加布尔变量标记是否正在离开房间,触发离开流程后跳过所有需要网络操作的逻辑:
private bool _isLeavingRoom; private void Update() { _currentPlayersCountText.text = PhotonNetwork.PlayerList.Length.ToString(); // 已触发离开流程,跳过网络操作逻辑 if (_isLeavingRoom) return; if (PhotonNetwork.IsMasterClient) { _startGameButton.GetComponent<Button>().enabled = PhotonNetwork.PlayerList.Length >= 5; Hashtable ht = PhotonNetwork.CurrentRoom.CustomProperties; ht["timer"] = _roomTimer.timeRemaining; // 直接赋值覆盖,无需先删除再添加 PhotonNetwork.CurrentRoom.SetCustomProperties(ht); } if (_roomTimer.timeRemaining <= 110) { _isLeavingRoom = true; LeaveRoom(); } }
2. 检查客户端连接状态
在调用SetCustomProperties前,额外校验客户端是否处于正常连接状态:
if (PhotonNetwork.IsMasterClient && PhotonNetwork.NetworkClientState == ClientState.Connected) { // 执行房间属性更新逻辑 }
3. 优化计时器更新频率
原代码每帧都更新房间属性属于过度调用,改为固定间隔更新(比如每0.5秒),既减少网络请求,也降低触发异常的概率:
private float _timerUpdateInterval = 0.5f; private float _lastUpdateTime; private Button _startGameBtn; private void Awake() { // 缓存按钮组件,避免每帧重复获取 _startGameBtn = _startGameButton.GetComponent<Button>(); } private void Update() { _currentPlayersCountText.text = PhotonNetwork.PlayerList.Length.ToString(); if (_isLeavingRoom) return; if (PhotonNetwork.IsMasterClient && PhotonNetwork.NetworkClientState == ClientState.Connected) { _startGameBtn.enabled = PhotonNetwork.PlayerList.Length >= 5; // 仅间隔指定时间才更新属性 if (Time.time - _lastUpdateTime >= _timerUpdateInterval) { _lastUpdateTime = Time.time; Hashtable ht = PhotonNetwork.CurrentRoom.CustomProperties; ht["timer"] = _roomTimer.timeRemaining; PhotonNetwork.CurrentRoom.SetCustomProperties(ht); } } if (_roomTimer.timeRemaining <= 110) { _isLeavingRoom = true; LeaveRoom(); } }
额外优化点
- 直接通过
ht["timer"] = value覆盖属性,无需先Remove再Add,简化代码 - 缓存
Button组件实例,避免每帧重复调用GetComponent消耗性能
内容的提问来源于stack exchange,提问作者Калашников Ян
相关产品推荐
相关产品推荐

