SKYXY客服
x
遊戲角色同步技巧 I — 角色登入與遠端生成 | skyxy
快速建站
︿
TOP
首頁 > 研究專題 > 文章內容
遊戲角色同步技巧 I — 角色登入與遠端生成
9/11/2016 10:51:43 AM
瀏覽數:854
沈夜
角色登入與遠端生成
前導:
在即時互動性需求較高的連線遊戲中,為了避免網路延遲的關係導致玩家的操控體驗不佳,我們可以透過隱藏延遲的技巧來修正。
 
本文件將會分開為兩個篇章做描述:
  1. 第一篇會將登入帳號、註冊帳號與修改暱稱的功能結合成登入畫面,並且分享一些使用arcalet-api的心得還有處理玩家登入/登出遊戲的流程。
  2. 第二篇則是針對隱藏延遲技巧的分析與應用。
開發佈署
在閱讀本文件之前,請開啟Assets/Scripts/AGCC目錄下的AGCC.cs,並且完成以上所需要的資訊,若這個步驟還不太熟悉可以參考下面的連結。
arcalet sample code - 開發佈署
輸入完上述需要的資訊之後,便可以試著用兩個以上的User連線,感受一下角色同步的過程。

註.本專案內容僅支援Standalone平台的操作
Login Scene 基本介紹
本範例的預設場景為 Login,存放路徑為 Assets > Scenes > Login
下列為Login Scene主要的GameObject與簡易的功能描述

- AGCC
 負責與arcalet server通訊,並且管理玩家的登入程序與連線狀態
 
- LoginManager
 負責與控管Login Scene的所有物件,並且與AGCC溝通
 
- LoginPart                  使用者登入介面
- RegistPart                         註冊帳號介面
- NicknamePart                 設定暱稱介面
- LoginProcess            登入時顯示的進度資訊
- MessageBox             錯誤訊息提示視窗

LoginScene接收到的按鈕事件都是由場景裡面各個Part的OnClick()發送的
uGUI系統並不在本範例的探討範圍內,相關用法請至下列連結查詢。
Unity - The New UI
LoginScene的操作動線如下圖,使用者藉由LoginPart、RegistPart或NicknamePart的按鈕發送事件給LoginManager,而LoginManager負責與AGCC溝通,AGCC則負責與arcalet server通訊,並將得到的callback結果回送到LoginManager,LoginManager再決定各個Part的顯示開關。
 
因為主要的程式邏輯都寫在LoginManager與AGCC這兩個腳本之中,在開發上如果遇到需要更動的地方可以比較快速的調整程式碼,而不用一次開太多腳本逐一修改。我們也可以每個Scene之中建立一個Manager負責與AGCC溝通。

示意圖:
AGCC
AGCC是由我們所定義---負責與arcalet server通訊、可以存活在各個場景並且與每個場景中的Manager溝通、且不會同時存在兩個以上,本章節將會針對AGCC在使用上該注意的事項做說明。
 
在本範例的架構下,使用者會隨著與arcalet的連線與斷線而在兩個場景中切換,而隨著重複進入Login場景的情況下,我們需要一個機制防止多個AGCC同時存在,請參考Assets/Scripts/AGCC目錄下的AGCC.cs。

示意圖:
為了確保AGCC的初始設定會比各個場景的Manger提早完成,我們可以將AGCC的初始設定寫在Awake function之中,各個Manger的初始設定則寫在Start function上。

或是由Project Setting > Execution Order去調整各個腳本的執行先後順序。
在AGCC的初始設定上,有幾點是需要注意的。
 
  1. 為了讓AGCC不會同時存在兩個以上,我們可以設定一個single tone的機制
  2. DontDestroyOnLoad()則可以讓AGCC存活在不同場景之中,
  3. 在Unity環境執行下則必須要呼叫ArcaletSystem.UnityEnvironment()。
帳號說明
關於使用者註冊帳號的用法有個技巧可以使用,我們可以讓使用者在成功註冊新帳號之後,能夠自動登入或者自動填入登入所需要的帳號密碼。這時候我們可以在呼叫API的時候一併製作存有這些資訊的token,當callback function被呼叫的時候再把token的內容取回來。
 
當使用者註冊新帳號時,username的長度必須在3~10個字元之間,且只接受英數字與符號字元desh[-]和dot[.]。password的長度必須在6~18個字元之間。
ArcaletGame
ArcaletGame在使用上也有需要注意的地方,一旦ArcaletGame呼叫過Launch()之後再次呼叫Launch()將會得到error code。
如果需要讓使用者重新登入,我們需要再建構一個新的ArcaletGame
SendOnClose的作用在於當使用者帳號離線時,arcalet sever會自動發送訊息的內容,我們可以在ArcaletGame成功登入之後就馬上呼叫SendOnClose將離線訊息儲存到arcalet server之中。
玩家的帳號在還沒設定過nickname之前,預設的value為空字串,我們可以根據這個值來判斷使用者是否設定過暱稱。
SetPlayerNickname() 並不是 static  function,這點需要注意一下。
一旦登入的帳號發生無法預期的斷線行為,OnStateChanged將會偵測到state大於900的情況,這時候我們可以加入下面區段內的程式碼來釋放ArcaletGame。
當應用程式關閉時,建議加入下面的機制確保釋放ArcaletGame,藉由呼叫Dispose()可以讓連線中的ArcaletGame強制登出。
訊息傳輸
本範例透過AGCC.cs的兩個函式---MainMsgIn()與PrivaMsgIn()來接收主大廳訊息與私人訊息,藉由收到的指令標頭來呼叫不同的函式。
如果我們不希望在AGCC.cs腳本中寫入太多的程式碼,可以藉由partial class將程式碼分開到其他的腳本撰寫。
使用者登入遊戲的處理流程
當使用者登入arcalet並且進入Game Scene,GameManager.cs會在Start函式發送主大廳訊息通知所有其他的遠端Client,所要傳送的訊息內容包含指令的標頭enter、用於辨別玩家的poid與顯示在角色頭上所要用到的nickname。
所有client在收到以enter為指令標頭的訊息之後,則執行位於AGCC_Game.cs中的PlayerEnter函式。
此函式主要用於解析訊息內容,並且取得需要的數據,呼叫GameManager.cs 的AddRemotePlayer函式並且生成對應的遠端角色到場景上。
此時剛登入的client還不知道有多少用戶存在於場景之中,因此我們可以讓每個已經存在於場景中的client透過SendLocalInfos函式發送本身的遊戲角色資訊給這位新登入的使用者。
新登入的使用者在收到各個client 傳來的訊息後,再執行PlayerAdd函式來解析訊息內容。
此函式取得需要的數據後將呼叫 GameManager.cs的 AddRemotePlayer函式並且生成對應的遠端角色到場景上,這邊所呼叫的AddRemotePlayer 與先前提到的是兩個不同的 overloading。
這兩個overloading最終目都是建立出對應的遠端角色,差別在於已經存在於場景上的角色通常不會在預設的位置上,這時候需要額外指定遠端角色的座標位置與方向。
List的特性很適合處理需要隨時新增或移除集合中某個元素的狀況。
當玩家登入或登出遊戲時,程式就可以藉由remotePlayers管理所有的遠端角色。
使用者登出遊戲的處理流程
一旦玩家登出arcalet,先前儲存在server之中的SendOnClose內容則會馬上發送到主大廳訊息,每個client收到指令之後開始執行相關的函式。
PlayerLeave函式用於解析訊息內容,並且取得登出帳號的poid
DeletRemotePlayer負責移除相關遠端玩家所有的GameObject與相關資料。
1
2
3
4
5
6
 Network Synchronize.zip  (34.17 MB)
您也可能喜歡這些文章
留言給作者
不公開此留言     登入即可留言
讀者留言
載入更多留言