【目次】
概念図による説明
サーバ起動からバトル開始までの流れ
マッチングルームへの入室
マッチングの成立可否
マッチングサーバからバトルサーバへの接続切り替え
バトルルームでの諸制御
バトルの終了
概念図による説明▲
prefork_battle_matching_lite の構成は以下のようになります。
上図をもとにそれぞれのサーバの役割について説明すると、以下のようになります。
【Matchingサーバ】
本システムに対し、クライアントが最初に接続するサーバになります。
マッチングルームの作成、マッチング成立の可否、クライアントの入退室を管理します。
【Battleサーバ】
マッチング成立後に、半自動的にクライアントが接続するサーバになります。
バトルルームの管理部分となる RoomHub(親プロセス)と、
バトル全般を管理する Battle(子プロセス)にて構築されます。
【BattlePuListサーバ】
クライアントとの接続は行いませんが、MatchingサーバとBattleサーバとを仲介する役割を果たします。
マッチング成立後のバトルルームの予約管理など、MatchingサーバとBattleサーバとの情報伝達用に用います。
【Syncサーバ】
モノビットエンジンで使用する各種サーバを管理しています。
サーバ起動からバトル開始までの流れ▲
■ 通信の流れについて
通信そのものはRPCにて制御されますが、RPCそのものについては「RPC編」にて纏めて説明します。
ここではサーバ起動からバトル開始までの流れについて、上図をもとに大まかに説明します。
【バトルサーバのprefork処理】
① Battle → RoomHub
バトルサーバ起動時に RoomHub に「クライアントが自身に接続するための情報」を送信する。
② RoomHub → BattlePuList
①で提供された情報に RoomHub 固有の情報を付加して BattlePuList に情報を送信する。
【マッチングルームへの入室】
① クライアント → Matching
マッチングルームへの入室依頼を送信する。
② Matching → クライアント
入室したマッチングルームの情報をクライアントに送信する。
【バトルルームの予約】
① Matching → BattlePuList
マッチングが成立していたら、BattlePuList にどのバトルに入るかの予約依頼を送信する。
② BattlePuList → RoomHub
BattlePuList でどのバトルに入れるかを判断後、その予約情報を RoomHub に送信する。
③ RoomHub → Battle
受け取った予約情報を、予約したバトルルームを管理する Battle に送信する。
④ Battle → RoomHub
バトルルームのステータスを「予約済み」に変更し、RoomHub へステータス変更内容を送信する。
⑤ RoomHub → BattlePuList
RoomHub 内で管理しているバトルルームのステータスを変更し、BattlePuListに有効なバトルルームの情報を送信する。
⑥ BattlePuList → Matching
予約したバトルルームとの接続に必要な情報を Matching に送信する。
【マッチングの成立可否】
① クライアント → Matching
マッチングが成立したか問い合わせる。
② Matching → クライアント
マッチングの状態をクライアントに送信する。
このとき【バトルルームの予約】が完了していれば、バトルに必要な情報もあわせて送信する。
【マッチングサーバからバトルサーバへの接続切り替え】
① クライアント → Matching
マッチングからの退室依頼を送信する。
② Matching → クライアント
マッチングからの退室依頼の結果を送信する。
③ クライアント → Battle
【マッチングの成立可否】によって得られたバトルルーム情報から、Battleに直接接続する。
【バトルルームへの接続】
① クライアント → Battle
バトルルームの状態を調べ、バトル可能かどうかを問い合わせる。
③ Battle → クライアント
バトルルームの状態をクライアントに通知する。
④ クライアント ←→ Battle
双方向で通信し、バトルを実行する。
【バトルルームからの切断】
① Battle → クライアント
バトルが終了した旨を通知する。
マッチングルームへの入室▲
ここからは、上述で触れた流れのうち、開発者がカスタマイズ可能な部分について触れていきます。
まずはマッチングルームへの入室処理です。
■ マッチングルームの入室依頼を送信する
まずクライアントから Matching サーバに対して、マッチングルームの入室依頼を送信します。
Unity クライアントからは、Assets/Projects/Scripts/sample/core/Client.cs にある
mln.Client.EnterMatchingRoom にて行っています。
赤枠で囲んでいる箇所が入室依頼を送信している部分になり、これ以降クライアントは「マッチング入室待ち」状態になります。
■ 入室したマッチングルームの情報をクライアントに送信する。
一方、この送信情報を受け取ったMatchingサーバ側では、入室可能なマッチングルームの情報をクライアント側に送信します。
この処理を行っているのが、server/matching/src/sample/RPC_BTL_Matching,cpp にある RPC_BTL_Matching::Recv_EnterMatchingRoom です。
ここでは赤枠で囲んでいる順に、「既設のマッチングルームの空きを調べる」「空きがないならルームを新設」「ルームに入室」「マッチング成否判定」
「入室結果をクライアントに送信」を実行し、クライアントに情報を送信する一方、マッチングが成立していた場合バトルルーム予約処理を実行します。
入室したマッチングルームの情報は、クライアント側にて Assets/Projects/Scripts/sample/pu/GameRpcClientPU.cs にある
mln.Battle.PU_Client.Recv_EnterMatchingRoomResult で受け取ります。
マッチングの成立可否▲
続けて、マッチングの成立可否です。
■ マッチングが成立したか問い合わせる
マッチング成立後のバトルルーム予約処理自体は、上述の通り、RPC_BTL_Matching::Recv_EnterMatchingRoom で行いますが、
バトルルームの予約はクライアントを介さずに行うため、クライアントはそのバトルルーム予約状況を把握できていません。
そのためクライアントから Matching サーバに対して、マッチングの成立可否を問い合わせます。
Unity クライアントからは、Assets/Projects/Scripts/sample/core/Client.cs にある
mln.Client.Update(case. m_Phase==PHASE.PHASE_MATCHING_CHECK_MATCHING_SUCCESS)にて行っています。
ここでは赤枠で囲んでいる箇所が成否問い合わせ送信をしている部分になり、これ以降、赤下線を引いた部分が成り立つまでの間
クライアントは「マッチング待ち」状態になります。
■マッチングの状態をクライアントに送信する。
一方、この送信情報を受け取ったMatchingサーバ側では、マッチングが成立しているかどうか、成立していた場合にはどのバトルルームを
予約しているかの情報をクライアントに送信します。
この処理を行っているのが、server/matching/src/sample/RPC_BTL_Matching,cpp にある RPC_BTL_Matching::Recv_GetMatchingStatus です。
それぞれ「マッチング成立」「マッチング待ち」「マッチング失敗」のどの状態にあるかをマッチングルーム情報から抽出します。
また「マッチング成立」時にはそのバトルルーム情報も同時に取得し、クライアントにマッチング状態を送信します。
一方クライアント側では Assets/Projects/Scripts/sample/pu/GameRpcClientPU.cs にある
mln.Battle.PU_Client.Recv_EnterMatchingRoomResult で受け取ります。
ここではマッチングが成立していた場合バトルルーム情報(プロセス情報)を受け取り、マッチング待ち以外の状態のとき
「マッチングルーム退室待ち」状態になります。
マッチングサーバからバトルサーバへの接続切り替え▲
マッチングが成立していた場合に、マッチングサーバからバトルサーバへ接続を切り替えます。
■ マッチングからの退室依頼を送信する。
まず Matching サーバに対し、退室依頼を送信します。
Unity クライアントからは、Assets/Projects/Scripts/sample/core/Client.cs にある
mln.Client.Update(case. m_Phase==PHASE_MATCHING_EXIT_ROOM)にて行っています。
■ マッチングからの退室依頼の結果を送信する。
この送信情報を受け取った Matching サーバ側では、マッチングからの退室依頼の結果を返します。
(ここは特に別段必要となる処理はしておりません。)
■ 【マッチングの成立可否】によって得られたバトルルーム情報から、Battleに直接接続する。
マッチングからの退室依頼の結果を受け取ったクライアント側では、Battleサーバに接続を開始します。
Unity クライアントからは、Assets/Projects/Scripts/sample/pu/GameRpcClientPU.cs にある
BTL.PU_Client.Recv_ExitMatchingRoomResultにて行っています。
以下の赤枠部分で囲まれたところが Matchingサーバからの切断、および Battle サーバへの接続処理で、
Battleサーバへの接続については 既に【マッチングの成立可否】によって得られたバトルルーム情報 m_BattlePuInfo を使い直接接続します。
バトルルームでの諸制御▲
バトルルームへ接続し終えたあとの諸制御です。
■ バトルルームの状態を調べ、バトル可能かどうかを問い合わせる
まずバトルサーバに対し、バトルルームの状態を調べてバトル可能かどうか問い合わせを行います。
Unity クライアントからは、Assets/Projects/Scripts/sample/pu/GameRpcClientPU.cs にある BTL.PU_Client.EnterRoom にて行っています。
■ バトルルームの状態をクライアントに通知する。
この送信情報を受け取った Battle サーバ側では、バトルルームへの入室処理を行い、結果をクライアントに送信します。
この処理を行っているのが、server/battle/src/RPC_BTL_Battle.cpp にある RPC_BTL_Battle::Recv_EnterRoom です。
バトルルームへの入室 EnterRoom() にて m_CharaInfoMap に接続しているクライアントの情報を格納した後、バトルの実行状態について
「バトルスタート」「途中参加」「カウントダウン(BattleWait)」のいずれかの状態に遷移させます。
他方で「途中参加」状態の場合については、即時バトル開始処理(Send_StartBattle)をクライアントに通達します。
※ なお、「バトルスタート」「カウントダウン」については、Battleサーバの内部処理にて適時 Send_StartBattle を呼び出しています。
その後、ここでは Send_StartBattle の送信処理について、クライアント側でどのような受信処理を行っているかについて解説します。
Unity クライアントからは、Assets/Projects/Scripts/sample/pu/GameRpcClientPU.cs にある BTL.PU_Client.Recv_StartBattle にて行っています。
ここでバトル中フラグ(m_IsBattle)が立てられ、バトル中の通信処理が出来るようになります。
■ 双方向で通信し、バトルを実行する。
m_IsBattle(m_pPU.IsBattle()) が true の際に実質的なバトル開始となります。
サンプルではチャットを送っているので、そのあたりを解説します。
チャット文字列の送信処理については Unity クライアント側の Assets/Projects/Scripts/sample/pu/GameRpcClientPU.cs にある
BTL.PU_Client.SendChat で行っています。
この送信情報を受け取った Battle サーバ側では、server/battle/src/RPC_BTL_Battle.cpp にある RPC_BTL_Battle::Recv_Chat にて
同一バトルルームにいるすべてのクライアント端末に対し、受信した文字列を Send_ChatResult() でそのまま送信しています。
なお、ここで使用している m_CharaInfoMap は、先のバトルルーム入室時に EnterRoom() にてクライアントの情報が格納されています。
更に上記でバトルサーバから送信された文字列情報は、各クライアント側の Assets/Projects/Scripts/sample/pu/GameRpcClientPU.cs にある
BTL.PU_Client_Recv_ChatResult で受け取ります。この中の ClientScene.Instance.Log() で画面ログに表示される文字列情報として
1行追記される形になります。
バトルの終了▲
最後にバトルの終了処理です。
■ バトルの終了時間について
バトルの終了時間については Battle サーバ側で管理しています。
場所は server/battle/src/game/pu/GameBattlePU.cpp 内の GameBattlePU::UpdateBattleStartLogic() にあります。
下記赤枠内の「 + 60」が制限時間(60秒)になっており、ここを変更することで制限時間を変更することができます。
また、server/battle/src/game/pu/GameBattlePU.cpp 内の GameBattlePU::UpdateBattleLogic()
にある
下記赤枠部分を削除することで、制限時間を無制限にすることが可能です。
■ バトルが終了した旨を通知する。
バトルの終了処理は、server/battle/src/game/pu/GameBattlePU.cpp 内の GameBattlePU::UpdateBattleEndLogic() 内で行っています。
下記赤枠内で行っているのが終了通知の部分で、Send_Chat と同様、同一バトルルームに存在するすべてのクライアントに一斉送信します。
受け取ったクライアント側では、Assets/Projects/Scripts/sample/pu/GameRpcClientPU.cs にある BTL.PU_Client.Recv_EndBattle にて
バトルの終了処理を行っています。ここでバトル中フラグ(m_IsBattle)が false にされ、
Assets/Projects/Scripts/sample/core/Clilent.cs の Update() 内のバトルの終了処理(m_Phase==PHASE.PHASE_BATTLE_END)に進みます。