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 ()
{
Dictionary data = 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 Dictionary requestDict = 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
}










留言
張貼留言