6-14 Using Dictionary To Manage All Request
繼上一章我們把登入以及註冊畫面完成後,本章要來進一步實作真正的登入功能啦!還記得之前我們跟Photon Server連線的時候,需要回傳許多byte作為辨識碼嗎?比方說OperationCode、ParameterCode啦之類的,再使用switch判別不同的byte執行不同的Request。小程式的時候使用switch還好,但大程式就非常不適合。
首先,我們需要將byte碼進行分類,不要讓Magic Number出現在程式碼裡面。新增三個Script分別名為EventCode, OperationCode, ParameterCode。
這三個Sctipt都是enum型別,並繼承自byte。以後要使用時,就可以透過OperationCode.Login使用。
接著在PhotonEngine.cs中新增Dictionary物件,分別儲存OperationCode跟我們自定義的Request物件。
Request物件是抽象類別,主要定義這個Request的OperationCode是什麼,以及OnDefaultRequest用來處理發送的事務,OnOperationResponse用來處理接收的事務。比方說登入的事情就交給LoginRequest處理,LoginRequest會繼承Request並實作這兩個抽象方法。以後有註冊的事情交給SignupRequest處理,透過類別分開所有的事務,會比起switch還好管理。
接著在PhotonEngine.cs中新增AddRequest與RemoveRequest方法。
回到Request.cs,Start的時候呼叫PhotonEngine將自己加入Dictionary中,OnDestory的時候也要將自己從Dictionary中刪除。
接著在PhotonEngine.cs中的OnOperationResponse中處理從Server傳回的訊息,取得OperationCode以後強制轉型為enum型別的OperationCode,然後從Dictionary中獲得相對應的Request物件,呼叫物件裡面的OnOperationResponse。如此一來,就完全脫離switch的寫法啦!
接著來實作LoginRequest吧,繼承Request,並實作OnDefaultRequest方法,將帳號密碼傳給Server。
在LoginWindow.cs中撰寫OnLoginButton方法,指定帳號密碼的參數到LoginRequest後,就可以呼叫OnDefaultRequest進行傳送的動作。
本章先介紹Client端的寫法,下一章再講解Server端的部分。以下提供目前為止有修改到的程式碼:
OperationCode.cs:
ParameterCode.cs:
Request.cs:
LoginRequest.cs:
LoginWindow.cs:
PhotonEngine.cs:
首先,我們需要將byte碼進行分類,不要讓Magic Number出現在程式碼裡面。新增三個Script分別名為EventCode, OperationCode, ParameterCode。
這三個Sctipt都是enum型別,並繼承自byte。以後要使用時,就可以透過OperationCode.Login使用。
接著在PhotonEngine.cs中新增Dictionary物件,分別儲存OperationCode跟我們自定義的Request物件。
Request物件是抽象類別,主要定義這個Request的OperationCode是什麼,以及OnDefaultRequest用來處理發送的事務,OnOperationResponse用來處理接收的事務。比方說登入的事情就交給LoginRequest處理,LoginRequest會繼承Request並實作這兩個抽象方法。以後有註冊的事情交給SignupRequest處理,透過類別分開所有的事務,會比起switch還好管理。
接著在PhotonEngine.cs中新增AddRequest與RemoveRequest方法。
回到Request.cs,Start的時候呼叫PhotonEngine將自己加入Dictionary中,OnDestory的時候也要將自己從Dictionary中刪除。
接著在PhotonEngine.cs中的OnOperationResponse中處理從Server傳回的訊息,取得OperationCode以後強制轉型為enum型別的OperationCode,然後從Dictionary中獲得相對應的Request物件,呼叫物件裡面的OnOperationResponse。如此一來,就完全脫離switch的寫法啦!
接著來實作LoginRequest吧,繼承Request,並實作OnDefaultRequest方法,將帳號密碼傳給Server。
在LoginWindow.cs中撰寫OnLoginButton方法,指定帳號密碼的參數到LoginRequest後,就可以呼叫OnDefaultRequest進行傳送的動作。
本章先介紹Client端的寫法,下一章再講解Server端的部分。以下提供目前為止有修改到的程式碼:
OperationCode.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; public enum OperationCode : byte { Login, Signup }
ParameterCode.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; public enum ParameterCode : byte { Acccount, Password }
Request.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using ExitGames.Client.Photon; public abstract class Request : MonoBehaviour { public OperationCode operationCode; public abstract void OnDefaultRequest(); public abstract void OnOperationResponse(OperationResponse operationResponse); public void Start(){ PhotonEngine.Instance.AddRequest (this); } void OnDestory(){ PhotonEngine.Instance.RemoveRequest (this); } }
LoginRequest.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using ExitGames.Client.Photon; public class LoginRequest : Request { [HideInInspector] public string account; [HideInInspector] public string password; public override void OnDefaultRequest () { Dictionarydata = new Dictionary (); data.Add((byte)ParameterCode.Acccount, account); data.Add((byte)ParameterCode.Password, password); // 向Server發出Request,true代表建立可靠連接 PhotonEngine.Instance.GetPeer().OpCustom((byte)operationCode, data, true); } public override void OnOperationResponse (OperationResponse operationResponse) { } }
LoginWindow.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class LoginWindow : Panel { [SerializeField] SignupWindow signupWindow; [SerializeField] InputField accountInput; [SerializeField] InputField passwordInput; [SerializeField] Text hintText; LoginRequest loginRequest; void Start(){ base.Start (); loginRequest = GetComponent(); } public void OnLoginButton(){ hintText.text = string.Empty; // 設定帳號及密碼參數後,呼叫OnDefaultRequest發送Request給Photon loginRequest.account = accountInput.text; loginRequest.password = passwordInput.text; loginRequest.OnDefaultRequest (); } public void OnShowSignupButton(){ this.Hide (); signupWindow.Show (); } }
PhotonEngine.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using ExitGames.Client.Photon; public class PhotonEngine : MonoBehaviour, IPhotonPeerListener { private DictionaryrequestDict = new Dictionary (); PhotonPeer peer; public static PhotonEngine Instance; void Awake() { if (Instance == null) { Instance = this; } else if (Instance != this) { Destroy (gameObject); return; } } void Start () { // 透過Listener回應伺服器的Response peer = new PhotonPeer (this, ConnectionProtocol.Udp); peer.Connect ("anoneko.cloudapp.net:5055", "NoliahFantasyServer"); } void Update () { // 必須在Update一直呼叫Service方法才能持續連線到Photon peer.Service (); } void OnDestroy(){ if (peer != null && peer.PeerState == PeerStateValue.Connected) { peer.Disconnect (); } } public PhotonPeer GetPeer(){ return peer; } public void AddRequest(Request request){ requestDict.Add (request.operationCode, request); } public void RemoveRequest(Request request){ requestDict.Remove (request.operationCode); } #region IPhotonPeerListener implementation public void DebugReturn (DebugLevel level, string message) { } // 接收由Server端傳回的Response public void OnOperationResponse (OperationResponse operationResponse) { OperationCode opCode = (OperationCode)operationResponse.OperationCode; Request request = null; requestDict.TryGetValue (opCode, out request); request.OnOperationResponse (operationResponse); } public void OnStatusChanged (StatusCode statusCode) { } // 接收由Server端發送的Event事件 public void OnEvent (EventData eventData) { } #endregion }
留言
張貼留言