欢迎大家继续学习《Unity 游戏编程进阶》
本节我们讲解 游戏房间界面的实现
本节将采用 PPT 讲解加项目演示的方式介绍游戏房间界面相关的知识要点
在项目演示环节，我们演示了游戏房间界面在《慕课英雄 2》项目中的具体应用
希望大家可以根据自己的专业基础和学习能力，从以下三种方法中选择一种来学习 第一种方法，先看
PPT 讲解，对相关知识有一个系统的了解，然后观看项目演示视频，学习知识点的运用
第二种方法，先看项目演示视频，了解知识要点的具体应用，再回到 PPT
讲解阶段，有针对性地学习相关知识要点 第三种方法，跳过 PPT 讲解，直接进入项目演示
通过理解项目中的知识要点的运用，完成相关知识要点的学习，不需回顾 PPT 讲解。
下面进入 PPT讲解阶段 玩家进入房间后 OnJoinedRoom
回调函数被调用，我们在该回调函数中启用 RoomPanel 游戏房间面板。
RoomPanel 游戏房间面板显示房间内玩家的信息 游戏房间内有且仅有一名房主，也就是
PUN 中的 MasterClient 它通常是创建游戏房间的玩家。
当创建游戏房间的玩家退出房间时，Photon 服务器
将指定房间的另一名玩家作为新的 MasterClient
在游戏房间面板中，玩家点击切换队伍按钮，选择自己所在的队伍 非
MasterClient 玩家点击准备按钮，切换自己的准备状态
所有玩家进入准备状态后，MasterClient 点击开始游戏按钮，所有玩家进入游戏战斗场景
下面我们讲解游戏房间面板 RoomPanel 的实现
[空白_录音] 本页 PPT
给出了游戏房间面板的各个 UI 控件 在 Hierarchy
层级视图中的组织结构，其中 RoomName 表示房间名称，TeamPanel
显示玩家的队伍信息和准备状态 SwitchButton 用于切换玩家的队伍
在非 MasterClient 玩家所在的客户端 ReadyButton
用于切换玩家的准备状态 在 MasterClient 所在的客户端，ReadyButton
用于开始游戏 PromptMessage 用于提示玩家操作失败
进入 房间后，玩家通过
Photon 服务器获得同意房间内其他玩家的信息 也可以通过 Photon 服务器向其他玩家发送信息。
PhotonPlayer 类用于保存玩家信息 PhotonPlayer 类包含了玩家的昵称和
ID 信息 我们可以使用 PhotonPlayer.SetCustomProperties
函数 设置玩家的自定义属性，自定义属性使用哈希表来保存 本页 PPT 给出了《慕课英雄
2》中玩家的自定义属性 其中 Team 表示玩家的队伍，TeamNum
表示玩家在队伍中的编号 isReady 表示玩家的准备状态，Score
表示玩家的得分 RoomPanelController
是游戏房间面板的控制脚本 我们在该脚本的 OnEnable
回调函数中，初始化游戏房间信息 首先我们使用 PhotonNetwork.room.name
获取房间的名称，其次清空玩家操作未成功的提示信息 promptMessage。
接着，根据房间最大人数计算每支队伍的最大人数 保存在
teamSize 变量中，然后调用 DisableTeamPanel
函数 禁用队伍面板中所有的玩家信息控件 最后，调用
UpdateTeamPanel 函数，在队伍面板中更新玩家信息
下面讲解 DisableTeamPanel
函数 我们遍历两支队伍的信息面板，获得玩家信息的显示控件
使用 SetActive 函数禁用这些控件
下面讲解 UpdateTeamPanel 函数
该函数用于更新队伍面板中的玩家信息 函数参数 isUpdateSelf
表示是否显示本地玩家的信息 UpdateTeamPanel
函数，遍历房间内的所有玩家 对于每个玩家首先获取 Team 和 TeamNum
属性，确定玩家信息显示的位置 然后在显示位置处填入玩家的昵称和状态。
如果玩家是 MasterClient 玩家状态栏显示房主，如果玩家不是
MasterClient 玩家状态栏显示玩家的准备状态
下面我们继续讲解 RoomPanelController 脚本的
OnEnable 函数 远程玩家的信息显示完毕后，本地玩家查找
队伍面板中空缺的位置，把自己的昵称和状态填入该位置 接下来设置玩家的自定义属性，玩家的
Team 和 TeamNum 属性 由该玩家在队伍面板中的位置决定。
玩家的 isReady 属性设为 false 表示玩家未准备。
玩家的 Score 属性设为 0，重置玩家的得分
[空白_录音] 在 Enable 函数的最后，调用
ReadyButtonControl 函数 设置本地客户端的 ReadyButton 按钮。
如果本地玩家是 MasterClient isMasterClient 的属性为
true，我们把 ReadyButton 按钮上的文字改为"开始游戏" 并把它的点击事件处理函数设置为
ClickStartGameButton 用于 MasterClient 开始游戏。
如果玩家不是 MasterClient isMasterClient 的属性为 false，我们把
ReadyButton 按钮上的文字改为"准备" 并把它的事件处理函数设置为
ClickReadyButton 用于玩家切换准备状态
下面讲解开始游戏按钮的事件处理函数，ClickStartGameButton MasterClient
点击开始游戏按钮，Unity 执行 ClickStartGameButton 函数
该函数遍历房间内的所有玩家，检查所有非 MasterClient
玩家是否都处于准备状态 如果有非 MasterClient 玩家未点击准备按钮，提示信息显示
有人未准备，游戏无法开始 如果所有非
MasterClient 玩家都处于准备状态 执行以下操作。
首先清除提示信息 然后设置 PhotonNerwork.room.open
属性为 false 禁止游戏大厅内的玩家进入该房间，最后使用
RPC 方法 让房间内所有玩家加载游戏战斗场景 GameScene
我们将在下一单元的课程中介绍 RPC 和游戏战斗场景 GameScene
[空白_录音] 下面讲解准备按钮的点击事件处理函数，ClickReadyButton
该函数对玩家的自定义属性 isReady 进行取反操作
切换玩家的准备状态，该函数还会根据玩家当前的准备状态 设置 ReadyButton 上的文字。
如果玩家处于准备状态 ReadyButton 上的文字设为"取消准备"。
如果玩家处于未准备状态 ReadyButton
上的文字设为"准备" 下面讲解切换队伍按钮的点击事件处理函数，ClickSwitchButton
该函数首先检查玩家的自定义属性 isReady 如果玩家
isReady 属性为 true，在 PromptMessage 提示信息框中显示
准备状态下不能切换队伍，使用 return 退出函数 如果玩家 isReady 属性为
false，遍历另一支队伍的 队伍信息面板，判断另一支队伍是否满员
如果另一支队伍未满员，就更改玩家的队伍属性 把
isSwitch 变量设置为 true，表示已切换队伍，如果另一支队伍已满员
则 isSwitch 变量仍为 false 在
ClickSwitchButton 函数的最后 读取
isSwitch 的变量的值，判断玩家是否成功切换队伍
如果切换失败，PromptMessage 显示另一支队伍已满，无法切换
如果切换成功，清空 PromptMessage 中的提示信息
下面讲解 返回按钮的点击事件处理函数。
玩家进入游戏房间后 返回按钮的功能变为返回游戏大厅。
首先使用 onClick .RemoveAllListeners
函数，移除返回按钮原有的事件处理函数 然后使用 onClick.AddListener
函数 给返回按钮绑定一个匿名的事件处理函数，在返回按钮的事件处理函数中
我们使用 PhotonNetwork.LeaveRoom
函数退出游戏房间 返回游戏大厅，然后使用 SetActive
函数启用大厅面板 禁用房间面板
最后我们讲解房间内玩家信息的更新 房间内玩家的信息会在四种情况下发生改变
第一种情况，房间内的玩家点击返回大厅按钮，退出房间
或者其他玩家在大厅中加入此房间，会引起房间内玩家数量的改变
第二种情况，玩家点击准备或取消准备按钮 会引起房间内玩家准备状态的改变。
第三种情况，玩家点击切换队伍按钮 就会引起玩家队伍信息发生改变。
第四种情况 MasterClient 离开房间，会引起房间内 MasterClient
的变更 当房间内玩家的信息发生改变时，房间内所有玩家都需要更新
游戏房间的 UI 显示，这里我们使用 Photon 的回调函数，OnPhotonPlayerPropertiesChanged
与 OnMasterClientSwitch，实现房间内玩家信息的更新
[空白_录音] 当房间内玩家的自定义属性发生改变时 PUN
会调用 OnPhotonPlayerPropertiesChanged 回调函数 我们在该回调函数中，完成房间内玩家信息的更新
首先调用 DisableTeamPanel 函数，禁用显示玩家信息的
UI 控件 接着，调用 UpdateTeamPanel 函数，将更新后的玩家
属性填入相应的玩家信息 UI 控件，显示在场景 UI 中 当房间内的
MasterClient 发生改变时 PUN 会调用 OnMasterClientSwitched
回调函数 在该函数中，我们调用 ReadyButtonControl 函数
将新 MasterClient 的 ReadyButton 上的文字改为"开始游戏"
并将它的点击事件处理函数设置为 ClickStartGameButton 函数
用于开始游戏 迄今为止，我们已经使用
PUN 完成了《慕课英雄 2》游戏大厅场景的开发 下一单元我们讲解如何使用
PUN 实现《慕课英雄 2》的战斗场景逻辑 下面是演示环节
我们演示游戏房间界面的制作