PUN2处于已加入房间状态时如何获取现有房间列表
问题核心原因
PUN2的原生连接状态逻辑存在互斥限制:客户端成功加入任意房间后,会自动退出之前加入的大厅,OnRoomListUpdate()作为大厅专属回调,仅会在客户端处于大厅连接状态时触发,原生不支持客户端同时驻留房间与大厅,这是服务端层面的默认规则,并非客户端调用逻辑错误。
可行实现方案
方案1:开启全局房间列表事件推送(最推荐,无额外性能损耗)
Photon服务端支持配置全局房间列表推送,开启后无论客户端处于大厅、房间哪个状态,都能收到房间列表的增量/全量更新,和你在大厅时收到的更新频率、数据格式完全一致,不会产生额外流量开销。
实现步骤:- 打开Photon控制台对应应用的配置页,在Webhook/实时通信配置项中开启「向所有在线客户端推送房间列表更新」开关,无需额外部署自己的服务。
- 客户端侧不再依赖挂载在MonoBehaviour上的
OnRoomListUpdate()回调,改为注册PUN全局事件监听,捕获内置的房间列表更新事件即可。
参考实现代码:
using Photon.Pun; using Photon.Realtime; using System.Collections.Generic; public class GlobalRoomListHolder : IOnEventCallback { // 全局缓存的房间列表,UI层直接读取这个数据做展示即可 public static List<RoomInfo> CachedRoomList { get; private set; } = new List<RoomInfo>(); public void Init() { PhotonNetwork.AddCallbackTarget(this); } public void Dispose() { PhotonNetwork.RemoveCallbackTarget(this); } public void OnEvent(EventData photonEvent) { // PUN内置房间列表更新事件码固定为228 if (photonEvent.Code == 228) { CachedRoomList = (List<RoomInfo>)photonEvent.CustomData; // 此处触发自定义的UI刷新逻辑,更新房间列表展示 } } }方案2:临时切换连接状态拉取列表(适合非实时拉取场景)
如果不需要在房间内实时刷新房间列表,仅在玩家主动点击「切换房间」按钮时才需要展示列表,可以用这个零配置的轻量方案:- 玩家触发切换房间入口时,先本地缓存当前所在房间的RoomName、自定义房间属性等必要信息。
- 调用
PhotonNetwork.LeaveRoom(),在OnLeftRoom回调中调用PhotonNetwork.JoinLobby()。 - 进入大厅后收到
OnRoomListUpdate回调拿到全量房间列表,弹出房间选择界面。 - 如果玩家取消选择房间,直接调用
PhotonNetwork.JoinRoom(之前缓存的原房间名)即可回到原房间。
注意:这个方案拉取列表期间玩家会短暂离开原房间,存在1-2s的连接延迟,需要做好加载态遮挡,不适合需要在房间内常驻展示房间列表的场景。
方案3:自定义房间列表同步(适合有复杂筛选需求的场景)
如果你的房间列表需要做自定义规则筛选(比如仅展示同玩法、同难度的房间),可以完全脱离PUN原生大厅逻辑,自行维护列表:- 所有房间创建成功后,将房间公开信息(房名、当前人数、玩法标签、地图ID)上报到自己的业务服务端,或者写入Photon全局自定义属性。
- 客户端无论处于什么连接状态,都可以通过请求业务接口、监听全局属性变更的方式拿到全量公开房间数据。
- 房间关闭、满员时主动上报服务端移除对应条目,定期清理异常掉线产生的脏数据即可。
这个方案灵活度最高,但需要自行处理列表一致性问题,开发量稍大。
避坑说明
- 不要尝试在客户端创建两个PUN连接分别驻留大厅和房间,PUN2原生不支持单客户端多实例连接,会出现回调错乱、连接频繁断开的问题。
- 不要在房间内高频调用
OpGetGameList接口主动拉取列表,该接口仅对大厅内的客户端生效,非大厅状态调用会直接返回错误,高频调用还会触发服务端限流。
内容的提问来源于stack exchange,提问作者iFralex
相关产品推荐
相关产品推荐

