Photon Unity Networking基础教程 2 Lobby UI
这部分将会集中于给Lobby创建用户界面。这部分的内容非常基础,并且跟网络关系不大。
主要内容
- Play按钮
- 玩家名字
- 连接进度
Play按钮
目前我们的Lobby是把我们自动连接到一个房间,这是有益于早期测试,但我们想让用户选择是否以及何时开始游戏。 因此,我们将简单地提供一个Button。
- 打开场景Launcher
- 使用Unity菜单'GameObject/UI/Button'创建一个按钮,命名为Play Button,注意他在场景中创建了Canvas和EventSystem游戏对象,省了我们的事了,nice:)
- 编辑Play Button的Text值为“Play”
- 选择Play Button然后定位到按钮组建的On Click()部分
- 点击小的加号“+”添加一条
- 把Launcher对象从Hierachy面板中拖过来
- 在下拉列表中选择Launcher.connect()函数。我们现在把按钮和Launcher脚本连起来了,当用户点击按钮的时候,将会调用Launcher脚本的connect()函数
- 打开Launcher脚本
- 把Start()函数中的connect()函数删除
- 保存Launcher脚本和场景
现在点击Play,你会发现需要点击按钮才能进行连接了。
玩家名字
典型游戏的另一个重要的最低要求是让用户输入他们的名字,以便其他玩家知道他们正在和谁玩。 我们将实现这个简单的任务,通过使用PlayerPrefs记住名字,以便当用户打开游戏,我们可以知道名字是什么。 要为您的游戏创建一个伟大的用户体验的话,这是一个非常方便和相当重要的功能。
让我们先创建一个脚本来管理和记住玩家的名字,然后创建相关的UI。
创建玩家名字输入框
-
创建一个新的C#脚本,命名为PlayerNameInputField
-
下面是脚本的全部内容,编辑然后保存
using UnityEngine; using UnityEngine.UI; using System.Collections; namespace Com.MyCompany.MyGame { /// <summary> /// Player name input field. Let the user input his name, will appear above the player in the game. /// </summary> [RequireComponent(typeof(InputField))] public class PlayerNameInputField : MonoBehaviour { #region Private Variables // Store the PlayerPref Key to avoid typos static string playerNamePrefKey = "PlayerName"; #endregion #region MonoBehaviour CallBacks /// <summary> /// MonoBehaviour method called on GameObject by Unity during initialization phase. /// </summary> void Start () { string defaultName = ""; InputField _inputField = this.GetComponent<InputField>(); if (_inputField!=null) { if (PlayerPrefs.HasKey(playerNamePrefKey)) { defaultName = PlayerPrefs.GetString(playerNamePrefKey); _inputField.text = defaultName; } } PhotonNetwork.playerName = defaultName; } #endregion #region Public Methods /// <summary> /// Sets the name of the player, and save it in the PlayerPrefs for future sessions. /// </summary> /// <param name="value">The name of the Player</param> public void SetPlayerName(string value) { // #Important PhotonNetwork.playerName = value + " "; // force a trailing space string in case value is an empty string, else playerName would not be updated. PlayerPrefs.SetString(playerNamePrefKey,value); } #endregion } }
下面分析一下这个脚本:
- RequireComponent(typeof(InputField))
我们首先保证这个脚本必须InputField组件,这可以方便快捷的保证使用该脚本没有错误。
- PlayerPrefs.HasKey(), PlayerPrefs.GetString() and PlayerPrefs.SetString()
PlayerPrefs是一个简单的配对条目的查找列表(像一个excel表有两列),一个是键,一个是值。 Key是一个字符串,是完全任意的,你决定如何命名,你需要在整个开发过程中记住它。因此,有必要总是将PlayerPrefs键存储在一个地方,一个方便的方法是使用Static变量声明,因为它不会随着时间的推移在游戏过程中改变,并且每次都是相同的。
所以,逻辑非常简单。如果PlayerPrefs有一个给定的键,我们可以得到它,并当我们要用的时候直接赋值。在我们的案例中,我们在启动时填充InputField时,在编辑过程中,我们把当前InputField的值设置给PlayerPref键,然后我们确定它被存储在用户设备上以供稍后检索(下一次用户打开此游戏)。
- PhotonNetwork.playerName
这是此脚本的要点,设置玩家在网络上的名称。 脚本在两个地方使用它,一次是在Start()中检查名称是否存储在PlayerPrefs中,一次是在公共方法SetPlayerName()中。 现在,没地方调用这个方法,我们需要绑定InputField OnValueChange()来调用SetPlayerName(),这样每次用户编辑InputField时,我们都会记录它。 我们可以做到这一点,只有当用户按下播放,这取决于你,但是这需要些更多的脚本,所以为了清楚起见让我们保持简单。 这也意味着,不管用户将做什么,输入将被记住,这通常是期望的行为。
为玩家的名字创建UI
- 确保你打开的是Launcher场景
- 使用Unity菜单'GameObject/UI/InputField'创建InputField,命名为Name InputField
- 把RectTransform中的PosY值设置为35,它会在PlayButton的上面
- 定位到Name InputField的子对象PlaceHolder,设置它的文本值为"Enter your Name..."
- 选择Name InputField对象
- 把我们刚才创建的PlayerNamerInputField脚本给它加上
- 定位到InputField组件的On Value Change (String)部分
- 点击加号“+”添加一条
- 把PlayerNamerInputField拖拽到框里
- 下拉列表中选择PlayerNameInputField.SetPlayerName()
- 保存场景
好了,你可以点击play运行,输入你的名字,然后停止play,再次点击play启动,你刚才输入的名字就会有了。
我们实现了功能,然而在用户体验方面,我们缺少连接进度的反馈,还缺少当连接期间和加入房间时出现问题时的反馈。
连接进度
我们在这里尽量保持简单,隐藏名称字段和play按钮,并在连接期间将其替换为简单的文本“正在连接...”,并在需要时将其切换回来。
为此,我们把播放按钮和名称字段做成一个组,以便我们只需要激活和停用该组。 后来更多的功能可以添加到组,它不会影响我们的逻辑。
- 确保你打开的是Launcher场景
- 使用unity菜单'GameObject/UI/Panel'创建UI面板,命名为Control Panel
- 删除Control Panel的Image和Canvas Renderer组件,我们不需要任何可视元素,我们只关心它的内容
- 把Play Button 和 Name InputField拖拽到Control Panel对象上去
- 使用unity菜单'GameObject/UI/Text'创建UI文字,命名为Progress Label,不用关心它影响了显示,我们将在运行时激活和停用它们
- 选择Progress Label的Text组件
- 设置对齐方式为center align和middle align
- 设置文字为“Connecting...”
- 设置颜色为白色或者其他和背景有区别
- 保存场景
此时,为了测试,您可以简单地启用/禁用Control Panel和Progress Label,以查看各种连接阶段的情况。 现在让我们编辑脚本以控制这两个GameObjects激活。
-
编辑脚本Launcher
-
在Public Properties区块添加下面两个属性
[Tooltip("The Ui Panel to let the user enter name, connect and play")] public GameObject controlPanel; [Tooltip("The UI Label to inform the user that the connection is in progress")] public GameObject progressLabel;
-
把下面的代码加入Start函数
progressLabel.SetActive(false); controlPanel.SetActive(true);
-
在Connect方法开头添加下面的代码
progressLabel.SetActive(true); controlPanel.SetActive(false);
-
在OnDisconnectedFromPhoton方法开头添加下面的代码
progressLabel.SetActive(false); controlPanel.SetActive(true);
-
保存Launcher脚本,等待unity编译结束
-
确保打开场景Launcher
-
在Hierarchy中选中Launcher对象
-
把Hierarchy中的Control Panel和Progress Label拖拽到对应的Launcher中的组件
-
保存场景
现在,如果你运行场景。 您将看到只有控制面板,可见,一旦您单击播放,将显示Progres标签。
到此为止,我们做好了Lobby部分。 为了进一步增加Lobby的功能,我们需要切换到游戏本身,并创建各种场景,以便我们可以在加入房间时最终加载正确的级别。 我们将在接下来的部分完成,然后,我们将完成Lobby系统。
原文
http://doc.photonengine.com/en-US/pun/current/tutorials/pun-basics-tutorial/lobby-ui
网友评论
public void SetPlayerName(string value) {
// #Important
value = this.GetComponent<InputField>().text;
PhotonNetwork.playerName = value + " ";//force a trailing space string in case value is an empty string,else playName would not be updated
PlayerPrefs.SetString(playerNamePrefKey, value);
}
并在OnEndEdit事件里面绑定,就可以了