マルチプレイヤーゲームの Client-Server 設計

2019-04-12   (Updated : 2019-04-24)

(この記事は未完成です)

はじめに

2019 年現在、スマートフォンゲームでもマルチプレイに対応したものが増えてきた。 現代を生きるゲーム開発者にとって、「他のプレイヤーと同期的な通信を行う」ゲームの Client-Server をきちんと作れるようになっておくことは重要だ。

ここでは「スマフォで動くライトな MOBA 風のゲームを作る」という要件で具体的な設計と技術選定を行い、 オンラインゲーム開発の周辺技術や知識を整理する。

要件

一口にマルチプレイと言っても求められる同期性のレベルによって、最適なアーキテクチャは変わってくる。 ここでは「リアルタイムに他のユーザの座標を同期する」ような、 ある程度アクション性のある対戦ゲームを想定する。例としては:

その他の要件は、現在の市場のニーズを鑑みつつ、以下のように設定する:

  • 日本向け(日本の通信インフラを前提とする)
  • iOS / Android で動く
    • Client は Unity (2018 以降) / C# (6 以降) で書く
  • プレイヤーはインターネットを介して通信する(キャリア回線 or 自宅 Wi-Fi)
  • Server を自分で立てる場合のインフラは AWS
  • ゲームは主にプレイヤーの管理画面と、メインのマルチプレイの 2 シーンを想定する
    • 一般的なソシャゲ向けの API サーバと、マルチプレイ用の速いサーバが必要になる
  • マルチプレイは 3 vs 3 のチーム戦とする
    • 俯瞰視点
    • ゆっくりめに移動してショットを撃ちあうような、ライトなアクションゲーム / シューター
    • ゲーム中にはキャラクターと壁と、何かしら作用のあるオブジェクトが存在する
シーン遷移のイメージ

シーン遷移のイメージ

要件には含めないもの

  • ターンベースで待ち合わせを行えばよいタイプのゲーム (Hearthstone やモンスターストライクのようなゲーム)は対象としない
  • 同時プレイの規模感も MMO ではなく MO とする
    • 最大でも 10 人程度
    • PUBG や Fortnite のような 100 人のバトルロイヤルも要件には含めない
  • 対戦格闘のようなシビアな同期性が求められるものも対象としない

周辺知識の整理

周辺技術や世の事例については以下にまとめた:

  • 基礎知識 / ネットワークモデル / HTTP2 / gRPC
  • 参考になる書籍 / Web 上の記事 / 事例集
  • Photon / UNET / モノビットエンジン / MagicOnion

ネットワークモデル

どのネットワーク構成にするか、ゲームロジックをどこに置くか、などを比較検討する。

評価指標

指標 詳細
到達可能性(Reachability) どういう環境で通信が成立するか
レイテンシ / RTT 通信速度。通信経路の長さやロジックの処理時間
スケーラビリティ 1 マッチで同時に何人プレイできるか
/ ゲーム全体で同時に何人さばけるか
ユーザ体験 ユーザが楽しく快適に遊べるか
セキュリティ / チート耐性 ゲームがチートされないか / ユーザが安全か
経済的コスト サーバの運用費など、金銭的なランニングコスト
開発・運用コスト(認知コスト / 複雑さ) 実装・環境構築の難易度
/ 保守・運用にエンジニアの労力がどれだけ必要か

P2P (Peer-to-Peer)

※ LAN 経由や、Bluetooth によるローカルプレイは今回は対象としない

サーバを介さず、スマフォ同士が直接通信する形式。 プレイヤーの一人が Host になって Guest は Host だけに接続するスター型と、 互いに情報を送り合うフルメッシュ型がある。

  • Host-Guest 形式は Host に負荷と通信量が集中する
  • フルメッシュ型の場合でも、アイテム取得などの排他的な処理を調停する調停役は必要である
Peer-to-Peer

Peer-to-Peer

  • 大抵の端末はインターネットに直接つながってはいないので、 NAT によってグローバル ip アドレスから変換されたプライベート ip アドレスを持つ
    • そのため、アドレスを直接指定して接続する P2P を実現するには NAT 越えを行う必要がある
NAT のイメージ

NAT のイメージ

P2P 形式の最大の利点はサーバ代がかからないことだが、課題やデメリットも多い:

指標 詳細
到達可能性(Reachability) NAT 越えが必要(越えられない環境もある)
レイテンシ / RTT 通信経路は最短になる
フルメッシュ型では全体の通信量が多くなり通信効率が悪い
スケーラビリティ ゲーム全体のプレイ人数に対してはスケールする
1 マッチの最大人数は多くできない
ユーザ体験 サーバ形式に比べ同期処理が安定しない
セキュリティ / チート耐性 Client がロジックを持つためチート耐性が無い
経済的コスト 最も安い。サーバが無いので、プレイ人数が増えても費用が増えない
開発・運用コスト NAT 越えの解決が必要
フルメッシュ型では各プレイヤーの同期が大変
動作確認や通信のデバッグが大変そう

P2P は 1 vs 1 の格闘ゲームのような、人数が少なく同期性が重視されるゲームだったり、 サーバ代をかけられないような案件向けの選択肢と考えてよいだろう。

Client-Server モデル

単にパケットを中継するだけのリレーサーバを置く形式と、 サーバ側でゲームロジックを処理する専用サーバ形式がある:

Client-Server モデル

Client-Server モデル

Client-Server という呼び方にすると不明瞭になる場合がありそうなので、 ここではどこにロジックが置かれるかという観点で 「クライアントホスト型」 「専用サーバ型」 という呼び分けをする。

※(文献を当たっていると、図中左のリレーサーバ形式を P2P と呼ぶ場合も Client-Server と呼ぶ場合もあるため。 また、Client-Server と言ってもスマフォ端末がサーバを兼ねるケースもあってややこしいため)


(A) クライアントホスト型

  • ゲームロジックが Client のランタイム上に置かれる(Unity 側で実装される)
  • Client のうち一台がゲームの調停役となる(Host-Guest 方式)
  • Server はリレーサーバで、単にパケットを中継するだけ

Photon Realtime(および PUN)、 UNETモノビットエンジンクラウド などの形式。 TURN サーバでリレーして NAT 越えを行う P2P も、これと同様の構造になる。

リレーサーバのサービスを使えば Client 側だけで実装が完結するため、 マルチプレイ実装の入門として選ばれることが多い印象。

指標 詳細
到達可能性(Reachability) NAT を越える
レイテンシ / RTT ホストのネットワーク環境に性能が左右される
スケーラビリティ サーバ側のスケールは容易
ホストに負荷が集中するので、1 マッチの最大人数に制約がかかる
ユーザ体験 ホストに高い通信性能が求められ、ゲームが続行不能になりやすい
ホストが有利になる(ゲストよりも先に状態の更新を知る)
セキュリティ / チート耐性 Client がロジックを持つためチート耐性が無い
経済的コスト 専用サーバと比べ、サーバ代が安く済む
開発・運用コスト Server が汎用的なもので済む
 (Client の実装だけ考えれば良くなる)
Server の知識は要らないが、Client には Host / Guest があり
  実装はそれなりに複雑になる
ホスト離脱時、ホストマイグレーションを考える必要がある


(B) 専用サーバ型

  • ゲームロジックが専用のゲームサーバ (Dedicated Game Server) 上に置かれる
  • 各 Client は Server が返す情報を正として、基本的にはブラウザのように振る舞う

Unity の新しいネットワーク機能はこの方針。 世のミドルウェアを利用する場合は Photon ServerMonobit Revolution Server が対象になる。

指標 詳細
到達可能性(Reachability) NAT を越える
レイテンシ / RTT ホスト型よりは、他のプレイヤーの通信環境の影響を受けにくくなる
スケーラビリティ サーバ側を適切に負荷分散すればスケールする。
  サーバが強ければ 1 マッチの最大人数も増やせる
ユーザ体験 サーバがコントロール下にあるという意味で、安定した
  プレイ環境を提供しやすい。復帰処理が実現しやすい
負荷が平等なのでゲーム全体が続行不能になりにくい
 (一部のプレイヤーが落ちても NPC に切り替えればゲームを続行できる)
セキュリティ / チート耐性 サーバでロジックが完結するのでチート耐性がある
経済的コスト リレーサーバよりもサーバの処理コストが上がるのでサーバ代がかかる
開発・運用コスト Client は Host / Guest を意識しなくて済む
Server やインフラの知見・管理コストが少なからず必要になる
Client / Server 双方の実装が必要になり、複雑度は上がる

どのモデルを採用するか

まず P2P か Client-Server かという選択においては、 スマートフォンがターゲットということもあり NAT 越えの問題 / 通信の安定性という観点から Client-Server が妥当 かと思う。

そうするとクライアントホストか専用サーバかという話になるが、個人的な結論は以下:

  • サーバの開発・管理コスト / 高めの維持費を払えるなら 専用サーバ型 が手堅い
  • サーバのコストを安く抑えたいなら、いくつかの観点を妥協して クライアントホスト型

クライアントホスト型の評価

  • チームメンバーの技術スタックが Client 寄りで、 Server のことはできるだけ考えたくないという場合はこれを選ぶだろう
  • カジュアルなマルチプレイ(ターンベースとか人数の少ない協力型とか)であればこれで十分と思う
    • 実際、日本のスマフォゲームにおいて多くの協力型マルチプレイはこの方式で実装されているようだ
  • しかしながら 3 vs 3 くらいの対戦アクションを実現するには、クライアントホスト型ではホストの荷が重い
    • (協力型のゲームと比べ、PvP となるとプレイヤー間の同期や平等性がより重視されるため、処理の妥協もしにくい)
    • 3 vs 3 を素朴に作った場合、Host と Guest のやり取りは以下のような図式になる:
ホストの負荷

ホストの負荷

  • ホストの CPU 負荷はもとより、ホストに集中するネットワーク帯域が厳しいだろう
    • ホストが万全な通信を維持できなくなった段階でそのマッチに参加する全プレイヤーがゲームが続行できなくなるので、 この方式では安定したプレイ環境は提供できない
    • 落ちたホストを NPC に変えて他のゲストにホストマイグレーションするという手法はあるが、 根本的な解決にはならない
    • (ホストマイグレーションは実装が複雑になるしデバッグが面倒そうというのもある)

専用サーバ型の評価

  • これが実現可能であるならば、モデルとして最も手堅いのは間違いない
    • 先に示したように、Client 側の負荷の分散や通信の安定性、チート耐性、同期のとりやすさなどの点で有利である
  • 不利になるのはサーバの開発・管理コスト、およびサーバの維持コスト

以下、リレーサーバを用いるクライアントホスト型と比較しつつコストを検討する。

サーバの開発・管理コスト
  • リレーサーバの場合は Photon などのサービスを利用すれば開発・管理コストをほぼゼロに抑えられる
    • 自分で用意する場合でも比較的やることは少なく、複数のゲームで使える汎用的な仕組みを作りやすい
  • 専用サーバを開発する際は、Server と Client で足並みを揃えて RPC を実装する必要がある
    • が、まあこれは Server を伴うスマフォゲーム開発ではよくあることなので、今さら何をという気はする
  • Server を実装する必要はあるが、その分 Client でのゲームロジック実装は減る
    • Host / Guest を意識する必要が無く、同期が取りやすいのでロジックは書きやすそう。 ホストマイグレーションを考えなくて良いというのも大きい
    • Client-Server 双方が作れるチームであれば、全体の実装コストはそんなに変わらないかも
サーバの維持費(AWS の費用)
  • 専用サーバ型はゲームステートを Server 側で保持して処理するので、 リレーサーバよりも CPU / メモリを多く消費する
    • インスタンス自体のスペックが求められる
  • 一方で、データ転送量に関してはリレーサーバでも専用サーバでも基本的には変わらないはず
    • クラウドはデータ転送量に対する費用が大きくなる印象がある。インスタンス代との比率はどうか?

AWS EC2 のインスタンス費用とデータ転送料金について、雑な試算をしてみる。

  • 料金は 2019-04 時点でのオンデマンドインスタンスの 公式の料金表 をもとにする
  • 1 USD = 110 円で換算する
  • インスタンス費用 について(1 台を 30 日稼働させた場合)
    • そこそこの CPU スペックである c5.2xlarge (vCPU 8 / ECU 34 / メモリ 16 GiB) : 33897
    • 手頃な汎用型 m5.xlarge (vCPU 4 / ECU 16 / メモリ 16 GiB) : 19642
    • ちなみに汎用型で一番高いやつ m5d.24xlarge (vCPU 96 / ECU 345 / メモリ 384 GiB) : 555034
  • データ転送料 について
    • 雑に 1 マッチあたりの転送量を「5 MB / 1 プレイヤー」とする
    • DAU 10000 で全ユーザが平均 3 回ずつプレイするケース → 日に 150 GB の転送量
    • 30 日間で 4500 GB の転送量
    • EC2 のデータ転送料金 = 56430
  • インスタンスに関しては、実際には手頃なスペックのものを複数台並べて負荷分散する構成が一般的だろう (台数ぶんの費用がかかる)
  • インスタンス費用がそれなりにかかるため、 やはりリレーサーバ形式よりもサーバの維持費がかさむことは覚悟しなくてはならない
通信ミドルウェアのライセンス料
  • 有償のミドルウェア(Photon Server など)を実装に用いる場合は、 サーバの維持費に加えてそのライセンス料がかかる

採用モデルの結論

費用面の問題はあるが、ゲームの要件に見合ったモデルは 専用サーバ型 である。

ここから先は、専用サーバ型で実装する想定で検討を進めていく。

アーキテクチャ / 技術選定

実際に何を使ってどう実装するかを検討していく。

(調査・実験・検討中……)