グローバル スケールのマルチプレーヤー型デモにより加速するマルチプレーヤー ゲーム開発
Nikolai Danylchyk
Customer Engineer
Mark Mandel
Developer Advocate
※この投稿は米国時間 2023 年 7 月 15 日に、Google Cloud blog に投稿されたものの抄訳です。
変化と競争の激しいマルチプレーヤー ゲームのバックエンドを構築する作業は複雑です。調整の必要な流動的要素が多くあり、プロダクトやソリューションの領域は、ほぼ無限大と言えるでしょう。オープンソース ソリューションや、評価、テスト、実装が必要なその他のソリューションをサポートするマネージド プロダクトは無数にあります。しかし多くの場合、それらすべてを相互に組み合わせて使用につなげていく過程は定まっていません。
この問題を解決して独自のマルチプレーヤー ゲーム構築の取り組みを開始するために、Google Cloud for Games の専門家からなる学際的なチームが団結し、変化の激しいマルチプレーヤー ゲームにおいてグローバル スケールの統合デモを作成しました。このデモの目的は、マルチプレーヤー ゲームのバックエンドをホスト、スケール、オーケストレートするために、Google Cloud が確認した本番環境で活用している以下のようなテクノロジーや手法を示すことです。その実例は、サービスやデータ ストレージから専用のゲームサーバーまで多岐にわたります。
デモで使われるテクノロジー例:
ゲームエンジン
- ゲーム クライアントおよび専用サーバーコード用の Unreal Engine 5
- クライアントサイド認証用のカスタム Go ゲーム ランチャー
- オープンソース
- Iinfrastructure as Code 用の Terraform
- 専用のゲームサーバーをホストティング、スケーリングする Agones
- グローバル プレーヤー ベースをマッチ メイキングする Open Match
Google Cloud
- 継続的インテグレーションとデプロイメントのための Cloud Build および Cloud Deploy
- バックエンド マイクロサービスをホスティングする GKE Autopilot
- Agones でオーケストレートされた Unreal 専用ゲームサーバーのホスティング用に実行する、グローバルに分散された GKE Autopilot および GKE Standard クラスタ
- クラスタ間サービス ディスカバリおよび通信のための Anthos Service Mesh
- プレーヤーのゲーム内データを保存するための Cloud Spanner
また、開発をさらに促進できるように、チームがこのプロジェクトに取り組む過程で学んだヒントとアドバイスも共有します。
Droidshooter
このデモの開発中に利用したサーバーサイドのテクノロジーと手法を明示し、簡単に検索できるようにするために、「Droidshooter」と呼ばれる非常にシンプルなマルチプレーヤー ゲームを計画的に構築しました。
このゲームは、小型宇宙船を操縦して他の 2 人のプレーヤーと対戦し、敵船にエネルギー バーストを発射して体力を奪おうというものです。敵船の破壊に成功するたびに、ポイントを獲得します。30 秒が経過した時点で最も多くのポイントを獲得しているプレーヤーが、そのラウンドの勝者となります。
アーキテクチャの概要
各コンポーネントの詳細に入る前に、アーキテクチャの概要を見てみましょう。
「Droid Shooter」のアーキテクチャの概要(クリックして拡大)
このゲームは世界中のオーディエンスを対象としているため、グローバルなインフラストラクチャ フットプリントを用意しています。
ゲームの一般的なバックエンド サービスは us-central1 でホストされています。レイテンシの影響を受けにくく、単一のリージョンとクラスタに統合することで管理がずっと簡単になるからです。プレーヤーとマルチプレーヤー型の専用ゲームサーバーとを接続するとレイテンシの影響を受けやすいため、世界中の複数のリージョンにあるそれぞれの Kubernetes クラスタにサーバーを配置し、必ずプレーヤーのロケーションに近接するようにします。
ゲーム状態のフロー
ゲーム クライアントの起動
上記のアーキテクチャにおいて、各プレーヤーは Game Launcher のインスタンスを開始します。これにより、Google ログインによる認証と、ゲームを起動するためのオプションが提供されます。
ゲーム状態のシーケンス図
データベースにプロファイル レコードが存在しない場合は、ログイン時に作成されます。その後、プロファイル サービスからプロファイル情報が取得され、(上記の名称の一つである)Launcher とゲーム クライアントに表示されます。
「Open Droidshooter」をクリックすると、ゲーム クライアントが起動し、フロントエンド サービスを通じてゲームをリクエストします。その後、ゲーム クライアントと前述の Launcher 用にホストされているバックエンド サービスへのほぼすべての通信に対し、認証されたエンドポイントを提供します。
マッチ メイキング
ここからは、クライアントはゲームサーバーがホストされる各リージョンで、グローバルな「ping ロケーション」一式をリクエストする必要があります。ゲームで最適なリアルタイム エクスペリエンスを得るために、低レイテンシであることが求められるためです。そのため、プレーヤーのロケーションから各リージョンの ping レイテンシを積極的に測定する必要があります。そうすることで、それぞれのロケーションからのレイテンシが似通ったプレーヤー同士をマッチングして、レイテンシが高すぎるリージョンを無視することができます。 残念ながら、プレーヤーを最も近いリージョンだけに送信することはできません。プレーヤー ベースが分割され、本来なら一緒にゲームできるはずのプレーヤーがマッチングできなくなるからです。
ゲーム クライアントは各リージョンの各レイテンシ測定エンドポイントを利用して各リージョンへのプレーヤーのレイテンシを記録します。その後、このデータを(認証されたフロントエンドを介して)マッチメイキング システムに送信し、他のプレーヤーがゲームできるようにグループ化をリクエストします。Droidshooter には非常にシンプルなマッチメイキング システムがあり、マッチメーカーは、レイテンシが最も近い 3 人のプレーヤーをマッチングさせようとします。
ゲームサーバーの割り当て
ゲームをプレイするグループが形成されると、マッチメーカーは、プレーヤーに最適な場所を決定したリージョンにおいて、ゲームサーバー オーケストレーション システムの専用のゲームサーバーをリクエストします。これらすべてのプレーヤーは同じエクスペリエンスを得る必要があるため、専用ゲームサーバーがゲーム世界の状態をシミュレートし、接続されているすべてのプレーヤーにリアルタイムでこの情報を伝達します。そうすることで、どのプレーヤーにとっても快適な Droidshooter エクスペリエンスが実現します。
したがって、ゲームの状態がメモリ内シミュレーションであることから、各クライアントが直接接続する必要のあるアドレスとポートは、マッチメーカーにより(フロントエンドを介して)ゲーム クライアントに返され、その後、Droidshooter がプレイされます。
最終クリーンアップ
ゲームが完了するとゲームサーバーは自動的にシャットダウンされますが、Google Cloud のゲームサーバー フリート管理システムにより、すぐに新しいサーバーがスピンアップされ、新しいプレーヤーがプレイできます。
エコシステムの内訳
上記のフローを実装するために使用した各プロダクトとオープンソース プロジェクト、およびそれぞれを選択した理由を見てみましょう。
Terraform
このプロジェクトを開始するにあたり、ゲームのバックエンドを実行するインフラストラクチャの作成を自動化するため、Infrastructure as Code をセットアップすることをまず最初に決定しました。そこで、オープンソースの Infrastructure as Code ソフトウェア ツールである Terraform を採用することにしました。これにより、宣言型の構成言語を通して、安全かつ予測可能なインフラストラクチャの作成や変更、改善ができるようになります。
このツールを選択した理由は、広く採用されていて、プロジェクトを開発中の各メンバーが互いに同じインフラストラクチャをセットアップできるうえ、最終エンドユーザーは、すでに使い慣れているツールを使用して同様のインフラストラクチャを自分で簡単にスピンアップできるからです。
ヒントとアドバイス
コード全体で Terraform 変数を十分に活用してください。一連の構成可能な変数により、エンドユーザーは、プロジェクトを完全なグローバル構成でスピンアップできます。また、開発目的としてより小規模で実行コストの低い構成を掲げることも可能です。
GKE Autopilot と GKE Standard
GKE Autopilot はフルマネージドの Kubernetes エクスペリエンスであり、実行する Pod に対してのみ料金を支払います。ホストの基盤となるインフラストラクチャについて心配する必要はありません。これは、プロファイルやフロントエンド サービスなどのカスタム サービス、Open Match プラットフォーム サービス(詳細は後述)など、あらゆるサービスに最適です。Autopilot で開発するうえでチームにとって特に良かった点は、構築中の新サービスや、それらを実行する GKE クラスタの容量を心配する必要がなかったことです。Autopilot によってインフラストラクチャが管理されていることがわかっていたので、デプロイするだけで済みました。
このデモでは、実際に GKE Standard と GKE Autopilot の両方でゲームサーバー コンテナをホストしています。本番環境では単一のプラットフォームを選択することが望ましいかも知れません。ただし、Autopilot の利便性がゲームサーバーのワークロードの要件に適する場合は、スタック全体で問題なく動作しますが、ゲームサーバーで、基盤となる GKE Standard ノードに特定の調整が必要となる場合は、GKE Standard も適切なソリューションになります。
ヒントとアドバイス
まずは Autopilot から始めて、必要な場合にのみ GKE Standard に移行してください。GKE Standard に移行する理由がない場合は、利便性のよい Autopilot で時間を大幅に節約できます。基盤はすべて Kubernetes であるため、プラットフォーム間の移行は非常に簡単です。
Agones
Agones は、Ubisoft と Google Cloud が独自に共同作成したオープンソースのゲームサーバー オーケストレーション プラットフォームですが、現在ではさまざまなゲームスタジオから 200 名を超えるコントリビューターが参加しています。このプラットフォームは、Kubernetes にはゲーム固有の最適化が必要であるという認識のもとに構築されており、Kubernetes に対してゲームサーバー ワークロードのライフサイクルを伝え、ゲーム中にプレーヤー エクスペリエンスが中断されないようにします。そのため、当チームでは、Agones の使用をすぐに決定しました。Agones がすべてを管理してくれるため、ゲームサーバーのライフサイクル管理やインフラストラクチャ使用の最適化を心配する必要がないからです。
Agones は API と SDK 一式も提供しているため、デモをプラットフォームに統合するのも簡単です。ゲーム状態の管理やプレーヤー管理などの機能が含まれているため、これらの機能をゼロから実装するのに必要な時間を大幅に短縮できます。
ヒントとアドバイス
Agones に付属の Terraform モジュールを活用して、GKE Standard クラスタと GKE Autopilot クラスタの両方を作成しましょう。クラスタの作成手順に沿って自分で作成することもできますが、Terraform モジュールならそこまで手間をかける必要もありません。
Open Match
Open Match はマルチプレーヤー ゲームのもう一つのオープンソース ツールで、Google Cloud と Unity Technologies が独自に共同開発しました。これは、ゲーム デベロッパーがスケーラブルで拡張可能なマッチメイキング システムを構築するのに有用なマッチメイキング フレームワークです。Open Match は、ゲーム デベロッパーが独自のマッチメイキング ロジックを作成するのに使用できるツールと API 一式を提供します。さらに、グローバル プレーヤー ベースをサポートするための基盤となるインフラストラクチャの管理もしています。
このプラットフォームを選択した主な理由は、マッチメイキング ロジックを完全にカスタマイズできるだけでなく、このマルチプレーヤー型ゲームデモで処理したいトラフィックに合わせてスケールできる機能も備えているからです。
ヒントとアドバイス
Open Match は、デプロイ先の 同じ Kubernetes クラスタ内でホストされている Redis のバージョンをバンドルしますが、Google Cloud 上でマネージド Redis サービス(高可用性、フェイルオーバー、パッチ適用、モニタリングなど)を提供する MemoryStore for Redis もぜひご活用ください。
GKE Autopilot で Open Match をホスティングすることをおすすめします。実行している Pod に対してのみ支払いが発生し、ノード インフラストラクチャを気にする必要がないため、Open Match の管理と維持がはるかに簡単になるからです。
Unreal Engine 5
Unreal Engine は、業界内での使用歴が長く、素晴らしいネットワーキング ツールを提供しています。また本番環境でも多くのデベロッパーが使用しているため、マルチプレーヤー ゲームの構築に最適です。Google Cloud では、このサンプルを本番環境ワークロードに合わせようとの試みがあり、採用はスムーズに決まりました。
Unreal Engine 5 の数ある利点の一つは、C++ と Blueprints の両方を介して、Agones とのシームレスなインテグレーションを実現できることです。Agones SDK が Unreal Engine 5 に統合されていると、デベロッパーは、ゲームサーバーのライフサイクル、構成、メタデータ、プレーヤーの追跡を管理しやすくなります。以下からソースをダウンロードして、直接プラグインを構築できます。https://github.com/googleforgames/agones/tree/release-1.30.0/sdks/unreal/Agones
ヒントとアドバイス
ゲームサーバーをホストしている各リージョンへのレイテンシ時間をクエリするには、Unreal Engine 5 ベースのクライアントも、いくつかの UDP パケットを Agones のレイテンシ テスト サービスに送信する必要があります。これに関するドキュメントを見つけるのは少し難しいかもしれませんが、Unreal のFUDPPing API を使用して、次のように UDP を介して ICMP Ping パケットを送信することができます。
FUDPPing::UDPEcho()
クラウドのエンジンとやり取りするための Unreal Engine コンテナ エコシステム(特に専用ゲームサーバーのコンテナ イメージの構築)は非常にうまく実装されており、スムーズなデベロッパー エクスペリエンスを実現します。ぜひ一度お試しください。
Cloud Build と Cloud Deploy
Cloud Build と Cloud Deploy は、いずれもマネージド Google Cloud Platform プロダクトであり、合わせて使用することで、アプリケーションの継続的インテグレーションと継続的デプロイを自動化し、GKE Standard および GKE Autopilot とも緊密に統合できます。今回のグローバル スケールのゲームデモでは、バックエンド サービス用と Unreal Engine 5 専用ゲームサーバー用にアーティファクトとイメージを作成(前述の Unreal Engine コンテナ システムを使用)するうえで Cloud Build と Cloud Deploy を使用しています。
Cloud Deploy には複数のクラスタをデプロイメント ターゲットとして任意にグループ化する機能があり、それが特に選ばれた理由でもあります。これにより、クラスタをリージョンごとにグループ化し、リージョンごとにロールアウトすることが可能になります。
つまり、オーストラリアなどの人口の少ない地域でデプロイをテストし、すべてが計画どおりに進むことが想定できれば、人口のより多い地域セットへと移行できるということです。
ヒントとアドバイス
生成された YAML が Cloud Deploy を通じてクラスタに適用され、それが 262144 バイトを超える場合は、
-- server-side kubectl
フラグを使用します。また、Kubernetes のServer Side Apply の所有権問題を処理するために-- force-conflicts
フラグと組み合わせてもよいでしょう。Deployment が正常な状態になるまでに何度か失敗する可能性がある場合は、Cloud Deploy の機能
tolerateFailuresUntilDeadline
を利用します。これにより、指定された期限まではシステムにより障害が許容されるようになります。これは、後のセクションで説明する Istio や Anthos Service Mesh で特に有用です。
Artifact Registry
Cloud Build と Cloud Deploy によって構築およびデプロイされたアーティファクトは、Artifact Registry コンテナ リポジトリに保存されます。Artifact Registry では、イメージ ストリーミングを通じてバックエンド サービスや専用ゲームサーバー イメージのスピンアップ時間が高速化されるだけでなく、脆弱性スキャンなどの利点も得られます。
Anthos Service Mesh
完全なグローバル スケールのゲームを構築するには、世界中に分散した一連の GKE クラスタ間で通信する方法が必要でした。これには、Google Cloud のバックエンド サービス クラスタや Agones クラスタも含まれます。これは、世界中の特定リージョンにある Agones 利用の GKE クラスタからゲームサーバーの割り当てリクエストをルートする必要があるため、Open Match ベースのマッチメーカーにとって特に重要です。
ありがたいことに、Google Cloud には Anthos Service Mesh が付属しています。これは、オープンソース プロジェクト Istio に基づいてマネージド サービス メッシュを提供するサービスです。これは、クラスタ内の DNS をベースとしたサービス ディスカバリに加え、マルチクラスタ通信の促進機能も提供するため、当チームのニーズに最適でした。
Istio の VirtualService
を使用する機能も重要でした。これにより、バックエンド サービス クラスタ内のすべての Agones Allocation REST エンドポイントに対して単一の DNS エントリを持ち、リクエスト内のカスタム リージョン HTTP ヘッダーを使用して特定のリージョンへのルーティングを提供できるようになります。同時に、Workload Identity によってアクセス制御とセキュリティを管理することも可能です。これで、多くの問題が一度に解決しました。
ヒントとアドバイス
Terraform ではまだサポートされていないオペレーションもあるため、
gcloud
を介して Anthos フリート管理を行うには、Cloud Build の使用を必要とする場合もあります。予期したマルチクラスタ Service DNS エントリが、それを必要とするクラスタ内に見つからない場合は、名前空間および一致する Service も同じクラスタ内に作成されているか確認してください。実装する必要はありませんが、DNS エントリの作成には、一致する名前空間と Service の両方が必要です。
Cloud Spanner
ゲームのリリースに関して以前からある問題は、どれだけのトラフィックが得られるかわからないということです。一方でリリースは非常に重要です。うまくいかなかった場合、リリース時に得られるはずだった水準にまでプレーヤー ベースを回復させるのは非常に困難だからです。
Spanner をデータ ストレージ プラットフォームに選ぶのは、まさにこれらの問題を解決するためです。Spanner は、マルチリージョン インスタンスに対して 稼働率 99.999% の SLA を備えた高可用性を実現します。また、リリース時に発生し得るあらゆる要求に合致する水平方向のスケーラビリティとグローバルな強整合性があるため、ゲーム内でプレーヤーに正確な情報が示されていることが常に確認できます。
ヒントとアドバイス
GKE クラスタは、インスタンス構成で定義されているように、地理的に Spanner の近くに配置して、書き込みと一貫した読み取りのリクエストのレイテンシを減らすことが重要です。この例では、バックエンド サービスが us-central1 にあるため、Spanner も us-central1 に配置しています。
Liquibase は、yami 構成ファイルを通じて Spanner スキーマの変更と更新を管理する優れたツールです。
アプリケーションを Spanner に接続できるように Workload Identity を構成するには複数の手順があり、正確に行うのは難しいかもしれません。これを解決するために、Terraform で作成された IAM 構成から Cloud Deploy yaml ファイルを生成し、インフラストラクチャのセットアップと継続的デプロイ構成の両方が手動での作業なしで調整されるようにしました。
まとめ
無数のオープンソース ツールやプロダクトの中からマルチプレーヤー ゲームを構築するためのプロダクト一式を選択するのは難しく、膨大な時間を要することもあります。グローバル スケールのマルチプレーヤー型ゲームデモの目的は、次にグローバル スケールのマルチプレーヤー ゲームを構築する際に使用できるガイドラインやアーキテクチャ パターン、構成要素を提供することです。
グローバル スケールのマルチプレーヤー型ゲームデモがこれからどのように成長していくか、とても楽しみです。今後の大きな計画として、このプロジェクトを成長拡大させながら、Google Cloud を使用してゲームをホスト、スケールするあらゆる方法を紹介します。
参加をご希望の場合、プロジェクトをご覧になりたい場合は、以下を参照してください。
- カスタマー エンジニア Nikolai Danylchyk
- デベロッパー アドボケイト Mark Mandel