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的鏈接。