Related Posts Plugin for WordPress, Blogger...

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:

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
}



留言