by 草帽php
不知不觉已经写到了第七篇这种类型的博客,可是回过头看看以前写的,发现都只能我本身能看懂。数据库
我相信在看的童鞋云里雾里的,由于我基本上没怎么详细讲一个脚本怎么用?可是大家能够本身看下代码,很快你就知道怎么用!之后也能够用到本身的项目中。缓存
因此说阅读别人的代码很是重要,由于大家从中发现他们代码的优势和缺点。服务器
OK,废话很少说,咱们继续上节课,上节课咱们已经封装本身的UI框架,可是还少个没讲,可能有些童鞋也会遇到报错,怎么解决?框架
在Window下新建一个UILib,而后里面新建一个脚本:ide
WidgetFactory:测试
using UnityEngine; using System.Collections.Generic; namespace UILib { public class WidgetFactory { /// <summary> /// 查找节点下全部的UI组件,缓存到字典里面 /// </summary> /// <param name="trans"></param> /// <param name="parent"></param> /// <param name="dicAllUIObjects"></param> public static void FindAllUIObjects(Transform trans, IXUIObject parent, ref Dictionary<string, XUIObjectBase> dicAllUIObjects) { int i = 0; while (i < trans.childCount) { Transform child = trans.GetChild(i); XUIObjectBase component = child.GetComponent<XUIObjectBase>(); if (!(null != component)) { goto IL_85; } if (component.GetType().GetInterface("IXUIListItem") == null) { if (dicAllUIObjects.ContainsKey(component.name)) { Debug.Log(component.name); Debug.LogError("m_dicId2UIObject.ContainsKey:" + WidgetFactory.GetUIObjectId(component)); } dicAllUIObjects[component.name] = component; component.Parent = parent; goto IL_85; } else { Debug.Log("fdsfd"); } IL_8F: i++; continue; IL_85: WidgetFactory.FindAllUIObjects(child, parent, ref dicAllUIObjects); goto IL_8F; } } /// <summary> /// 取得该组件所在的id(包含父亲节点的id) /// </summary> /// <param name="uiObject"></param> /// <returns></returns> public static string GetUIObjectId(IXUIObject uiObject) { string result; if (null == uiObject) { result = string.Empty; } else { string text = uiObject.CacheGameObject.name; IXUIListItem iXUIListItem = uiObject as IXUIListItem; if (iXUIListItem != null) { text = iXUIListItem.Id.ToString(); } while (null != uiObject.Parent) { uiObject = uiObject.Parent; string arg = uiObject.CacheGameObject.name; iXUIListItem = (uiObject as IXUIListItem); if (null != iXUIListItem) { arg = iXUIListItem.Id.ToString(); } text = string.Format("{0}#{1}", arg, text); } result = text; } return result; } } }
这个脚本主要是用来找UI的子物体用的。动画
OK,咱们正式进入到LoginWindow的完善。咱们知道这个界面分为两块,一个是登录,一个选择服务器。网站
咱们先来写登录的逻辑。ui
能够看到这个界面分为3个组件:
1.用户名输入框
2.密码输入框
3.确认登录按钮
因此咱们在LoginWindow初始化这些组件:
而后在InitWidget()里面初始化这些定义的组件:
这里的名字是我本身去的好比Login/UserNameInput,大家能够本身取本身的名字。
Login是LoginWindow下面的子物体,而后UserNameInput是Login下面的子物体,咱们用/来区分紫武器。
OK,当咱们点击确认登录按钮的时候,确定须要一个登录事件给这个按钮,因此如今咱们来写这个事件监听。
而后咱们来编写OnLoginSumbit方法,主要处理一些登录逻辑的事情。
public void OnLoginSumbit(GameObject go) { string username = this.m_Input_UsernameInput.value; string password = this.m_Input_PasswordInput.value; //若是用户名或者密码为空的话,就显示提示消息 if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) { CEvent evt = new CEvent(EGameEvent.eGameEvent_ShowMessage); evt.AddParam("content", StringConfigManager.GetString("MessageWindow.EMT_SureTip.LoginNullUsernameOrPassword")); EventCenter.SendEvent<EMessageType, Action<bool>>(evt, EMessageType.EMT_SureTip, (isOk) => { EventCenter.Broadcast(EGameEvent.eGameEvent_HideMessage); }); } LoginCtrl.singleton.Login(username, password); }
能够看到咱们搞了一个当肯定消息提示,若是用户名和密码为空的话。
而后为了符合类的单一职责,咱们把全部的逻辑放在LoginCtrl中。
新建文件夹取名为Controller,而后在里面新建一个LoginCtrl类:(我忘记以前是否是讲过这个类,若是有讲过这个类,由于我过久以前写的,都忘记了,读者自行改过)。
在写这个逻辑以前,咱们先来想下咱们登录进去在选择服务器,因此登录这个验证并无进入到游戏服务器中,由于咱们根本没有选择服务器,怎么能进到服务器中呢?
因此我认为就只是网页简单的验证用户名密码,而后选择服务器以后才真正的进入到游戏服务器。
因此这个登录的逻辑步骤是:
1.开启协程访问一个网站,这个网站验证用户名和密码。(因此我决定用PHP来写这个验证)
2.若是验证经过以后,而后发送服务器列表给客户端,客户端再进入到选择服务器界面。
3.客户端选择某个服务器,而后进入到这个游戏服务器。
因此首先,我在网站文件夹下面新建一个check.php文件:
这个脚本就是经过数据库链接,而后进行验证,这里我简单一点,我就直接都放回成功。由于咱们只是作下测试,不用每步都详细。
因此我这里只是简单放回一个success字符串,而后在LoginCtrl中:
public void Login(string account, string password) { this.username = account; this.password = password; LOLGameDriver.Instance.StartCoroutine(CheckUserPass()); } IEnumerator CheckUserPass() { if (string.IsNullOrEmpty(this.username) || string.IsNullOrEmpty(this.password)) { yield break; } WWW www = new WWW("http://127.0.0.1/LOLGameDemo/check.php"); bool success = false; for (int i = 0; i < 10; i++) { yield return new WaitForSeconds(0.5f); if (www.isDone) { if (string.IsNullOrEmpty(www.error)) { if (!string.IsNullOrEmpty(www.text)) { if (www.text == "success") { //加载服务器信息 SystemConfig.LoadServerList(); success = true; EventCenter.Broadcast(EGameEvent.eGameEvent_ShowSelectServerList); } else { //登录失败 } } } else { this.m_log.Error(www.error.ToString()); } break; } } if (www != null) { www.Dispose(); www = null; } //若是不成功 if (!success) { } yield break; }
不知读者注意到没有,若是登录成功的话,咱们就开始加载服务器列表。
//加载服务器信息 SystemConfig.LoadServerList();
因此咱们回到SystemConfig里面:
/// <summary> /// 加载服务器列表 /// </summary> public static void LoadServerList() { try { List<ServerInfo> servers; var url = GetCfgInfoUrlByName("ServerList"); string xmlSerList = ""; if (!string.IsNullOrEmpty(url)) { xmlSerList = DownloadMgr.Instance.DownLoadHtml(url); } servers = LoadXMLText<ServerInfo>(xmlSerList); if (servers.Count != 0) { ServerList = servers; } for (int i = 0; i < ServerList.Count; i++) { if (ServerList[i].id == LocalSetting.SelectedServer) { SelectedServerIndex = ServerList[i].id; break; } } } catch (Exception e) { m_log.Error(e.ToString()); } }
/// <summary> /// 根据名字取得服务端配置信息Url /// </summary> /// <param name="name"></param> /// <returns></returns> public static string GetCfgInfoUrlByName(string name) { string result = ""; foreach (var item in CfgInfoList) { if (item.name == name) { result = item.url; break; } } return result; }
而后咱们到Cfg.xml文件添加这个url=>id是1,名字是ServerList:
<?xml version="1.0" encoding="utf-8"?> <root> <cfg> <id>0</id> <name>version</name> <url>http://127.0.0.1/LOLGameDemo/ServerVersion.xml</url> </cfg> <cfg> <id>1</id> <name>ServerList</name> <url>http://127.0.0.1/LOLGameDemo/ServerList.xml</url> </cfg> </root>
而后咱们添加4个游戏服务器,分别是电信2个(type为0),联通两个(type为1):
<?xml version="1.0" encoding="utf-8"?> <root> <list> <id_i>0</id_i> <name_s>艾欧尼亚</name_s> <type_i>0</type_i> <flag_i>0</flag_i> <text_s>fe</text_s> </list> <list> <id_i>1</id_i> <name_s>战争学院</name_s> <type_i>0</type_i> <flag_i>0</flag_i> <text_s>csc</text_s> </list> <list> <id_i>2</id_i> <name_s>黑色玫瑰</name_s> <type_i>1</type_i> <flag_i>0</flag_i> <text_s>greger</text_s> </list> <list> <id_i>3</id_i> <name_s>洛克萨斯</name_s> <type_i>1</type_i> <flag_i>0</flag_i> <text_s>greger</text_s> </list> </root>
因此咱们回到LoginWindow中,添加该事件:
protected override void OnAddListener() { EventCenter.AddListener(EGameEvent.eGameEvent_ShowSelectServerList, ShowSelectServer); }
protected override void OnRemoveListener() { EventCenter.RemoveListener(EGameEvent.eGameEvent_ShowSelectServerList, Show); }
在写ShowSelectServer方法以前,咱们得先定义选择服务器界面组件:
#region 选择服务器界面 private UIPanel m_Panel_Select;//选择服务器界面总体Panel private UIButton m_Button_Select;//确认选择按钮 private UIButton m_Button_LeftButton; private UIButton m_BUtton_RightButton; private UIButton m_Button_ServerListButton;//服务器列表按钮 private XUIList m_List_Dianxin; private XUIList m_List_Wangtong; private XUISprite m_Sprite_IconBG; private XUISprite m_Sprite_ServerName; private XUISprite m_Sprite_Icon; private XUILabel m_Label_ServerName; private XUILabel m_Label_NetworkSpeed;//测试速度Label #endregion
InitWeight:
this.m_Button_ServerListButton = this.mRoot.FindChild("Select/Button/ServerListButton").GetComponent<UIButton>(); this.m_Button_Select = this.mRoot.FindChild("Select/Button/SelectButton").GetComponent<UIButton>(); this.m_Panel_Select = this.mRoot.FindChild("Select").GetComponent<UIPanel>(); this.m_List_Dianxin = this.mRoot.FindChild("Select/ServerList/Table/Dianxin/DianxinGrid").GetComponent<XUIList>(); this.m_List_Wangtong = this.mRoot.FindChild("Select/ServerList/Table/Wangtong/WangtongGrid").GetComponent<XUIList>(); this.m_Sprite_IconBG = this.mRoot.FindChild("Select/Signal/IconBG").GetComponent<XUISprite>(); this.m_Sprite_Icon = this.mRoot.FindChild("Select/Signal/IconAnim").GetComponent<XUISprite>(); this.m_Sprite_ServerName = this.mRoot.FindChild("Select/Signal/Name/ServerNameIcon").GetComponent<XUISprite>();
OK,初始化好界面后,咱们回过头写ShowSelectServer:
/// <summary> /// 显示选择服务器界面 /// </summary> public void ShowSelectServer() { if (this.m_Panel_Select != null) { if (this.ShowServerList()) { //服务器列表按钮的sprite替换 if (this.m_bShowServerList) { this.m_Button_ServerListButton.normalSprite = "image 378"; } else { this.m_Button_ServerListButton.normalSprite = "image 383"; } this.m_Panel_Select.enabled = true; GameObject serverList = this.m_Panel_Select.transform.FindChild("ServerList").gameObject; //serverList. serverList.SetActive(this.m_bShowServerList); //若是显示服务器列表面板,播放偏移动画 if (this.m_bShowServerList) { serverList.transform.localPosition = new Vector3(14, 0, 0); TweenAlpha.Begin(serverList, 1, 1); TweenPosition.Begin(serverList, 1, Vector3.zero); } } else { Debug.LogError("服务器列表尚未初始化"); } } }
/// <summary> /// 显示服务器列表 /// </summary> public bool ShowServerList() { if (this.m_bHasLoadedServerList) { return true; } if (SystemConfig.ServerList != null) { this.m_selectedServerId = SystemConfig.SelectedServerIndex; this.m_lastSelectServerId = SystemConfig.SelectedServerIndex; int indexDianxin = 0; int indexWangtong = 0; foreach (var serverInfo in SystemConfig.ServerList) { IXUIListItem serverItem; switch (serverInfo.type) { case 0: if (serverInfo.flag == (int)ServerType.Recommend) { this.m_reDianxinServerId = serverInfo.id; } if (indexDianxin < this.m_List_Dianxin.Count) { serverItem = this.m_List_Dianxin.GetItemByIndex(indexDianxin); } else { serverItem = this.m_List_Dianxin.AddListItem(); } if (serverItem != null) { serverItem.SetText("ServerName",serverInfo.name); serverItem.SetVisible(true); serverItem.TipParam = new TipParam { Tip = serverItem.Tip }; serverItem.Id = serverInfo.id; } else { serverItem.SetVisible(false); } indexDianxin++; break; case 1: if (serverInfo.flag == (int)ServerType.Recommend) { this.m_reWangtongServerId = serverInfo.id; } if (indexWangtong < this.m_List_Wangtong.Count) { serverItem = this.m_List_Wangtong.GetItemByIndex(indexWangtong); } else { serverItem = this.m_List_Wangtong.AddListItem(); } if (serverItem != null) { serverItem.SetText("ServerName", serverInfo.name); serverItem.SetVisible(true); serverItem.TipParam = new TipParam { Tip = serverItem.Tip }; serverItem.Id = serverInfo.id; } else { serverItem.SetVisible(false); } indexWangtong++; break; } } this.m_bHasLoadedServerList = true; return true; } else { return false; } }
#region 变量定义 private bool m_bShowServerList = false;//是否显示服务器列表 private bool m_bHasLoadedServerList = false;//是否已经加载过服务器列表 private int m_selectedServerId = -1; private int m_lastSelectServerId = SystemConfig.SelectedServerIndex; private int m_reDianxinServerId = -1;//电信推荐服务器id private int m_reWangtongServerId = -1;//网通推荐服务器idn #endregion
而后在InitWeight中,让m_Button_ServerListButton监听显示服务器列表和不显示的事件监听:
UIEventListener.Get(this.m_Button_ServerListButton.gameObject).onClick = (x) => { this.m_bShowServerList = !this.m_bShowServerList; ShowSelectServer(); };
还有咱们点击某个服务器,得把那个服务器的id,记录下来,因此咱们仍是注册一个事件:
this.m_List_Dianxin.RegisterListOnClickEventHandler(new ListOnClickEventHandler(this.OnServerListItemClick));
/// <summary> /// 服务器某个被点击 /// </summary> /// <param name="item"></param> /// <returns></returns> private bool OnServerListItemClick(IXUIListItem item) { if (null == item) { return false; } this.m_selectedServerId = item.Id; ServerInfo info = SystemConfig.GetServerInfoById(this.m_selectedServerId); bool active = true; if (info.flag == (int)ServerType.Close || info.flag == (int)ServerType.Maintain) { active = false; } ShowServerSignal(active, info); return true; } /// <summary> /// 播放动画 /// </summary> /// <param name="bActive"></param> /// <param name="info"></param> private void ShowServerSignal(bool bActive,ServerInfo info) { if (bActive) { if (info.id == 0) { this.m_Sprite_Icon.SetSprite("image 967", "Atlas/SelectAtlas/SelectServerAtlas"); this.m_Sprite_ServerName.SetSprite("image 975"); } else { this.m_Sprite_Icon.SetSprite("image 1015", "Atlas/SelectAtlas/SelectServerAtlas"); this.m_Sprite_ServerName.SetSprite("image 1012"); } if (this.m_Sprite_IconBG != null) { this.m_Sprite_IconBG.PlayFlash(false); this.m_Sprite_ServerName.Alpha = 0f; this.m_Sprite_Icon.Alpha = 0f; TweenAlpha.Begin(this.m_Sprite_ServerName.gameObject, 0.8f, 1f); TweenAlpha.Begin(this.m_Sprite_Icon.gameObject, 0.8f, 1f); } } }
OK,大体就是这么多的代码,具体步骤:
1.若是选择服务器Panel不激活的话,就显示服务器列表,而后激活。
2.注册一些按钮的事件
3.记录下来选择的服务器id
而后咱们点击选择按钮,就发送这个服务器id给游戏网关服务器,网关服务器就把用户链接到这个游戏服务器中。
下节课,咱们就开始进入游戏服务器链接,固然这里就涉及到NetworkManager的编写,主要是TCp的链接。