Hosting with Gameye
この機能はPhoton Bolt Proバージョンで利用できます。
Gameye は、不可知論的なインフラストラクチャを使用してゲームサーバーを世界中に展開するホスティングサービスです。
Photon Boltは Gameye
上の実行に対応しています。このチュートリアルでは、数分でゲームサーバーを開始してデプロイを行います。
Gameyeサービスについて
Gameye
サービスはDocker Containersを使用した仮想化を中心に構築されており、各コンテナーはプレイヤーをリッスンするゲームサーバーです。
REST APIを使用してこれらのゲームサーバーを簡単に作成、削除、一覧表示できるため、サーバーのオーケストレーションと自動化を行うのに最適です。
サービス自体の詳細については、公式ウェブサイトhttps://gameye.com/ とドキュメントページhttps://docs.gameye.com/をご覧ください。
ワークフロー
このチュートリアルでは、専用のゲームサーバーを実行し、Photon Bolt Proを使用して直接接続できるようにする方法に焦点を当てます。
次の手順に従います。
- ヘッドレスゲームサーバーを構成します。
Gameye
サービスにサーバーコンテナーをデプロイし、専用サーバーを起動します。- リモートサーバーを検索して接続できるゲームクライアントを構築します。
これらの各ステップには、いくつかのサブステップがあります。次のセクションで説明します。
このスキームを構築するために必要なファイルはすべてオープンソースプロジェクトとして利用できます。
構築するパーツの概要画像:
前提条件
必要なすべてのパーツの作成を始める前に以下のことを確認してください。
- Photon Bolt Proを保持していること。このサンプルは、Proバージョンの直接接続機能で使用することを前提としています。
- 独自の
Application Token
を受け取り、サービスにアクセスするために、Gameye
のスタッフにお問い合わせください。通話の認証に使用されます。 - DockerとDockerHubがどのように機能するかについての基本的な知識が必要です。
dockerイメージ
とdockerコンテナー
を構成、ビルド、実行、アップロードする方法も理解する必要があります。また、以下を保持している必要があります:DockerHub
アカウント(まだお持ちでない場合)。- サーバーイメージをアップロードするリポジトリ。
- 基本的なBoltチュートリアル(
Getting Started
およびAdvanced Tutorial
)を完了してください。 - Unityエディターに
Linux Target Platform
をインストールしてください。
ヘッドレスゲームサーバーを構築する
Gameye
で専用サーバーを実行するには、次のソリューションが必要です。(i)ヘッドレスサーバーを実行して接続をリッスンするUnityプロジェクト、(ii)サーバーバイナリをdockerイメージにカプセル化する
。後でアプリケーションをコンテナ化するために使用されます。
Unityプロジェクト
受け取ったSDKパッケージ内に、 samples_pro
というフォルダーがあります。このフォルダーには、他のサンプルプロジェクトと GameyeIntegration
というフォルダーが含まれています。
ヘッドレスサーバーを実行するために必要なすべてのファイルが含まれています。
次に、ゲームサーバーで使用されるいくつかのコードについて説明します。
Scenes
フォルダーには、このサンプルで使用する3つのメインシーン、(i) GameyeHeadlessServer
、(ii) GameyeInGame
、および(iii) GameyeClient
があります。
ゲームサーバーでは、最初の2つのシーンを使用します。
GameyeHeadlessServer
シーンから開始し、 GameyeServer
スクリプト(ゲームサーバーを制御するためのメインのエントリポイント)を実行する1つの単純な Game Object
のみを使用します。
このスクリプトはとてもシンプルです。
スクリプトは、BoltLauncher.StartServer(serverPort)
を呼び出して GameyeInGame
シーンを読み込むことにより、Boltサーバーを起動します。
ただし、注意が必要ないくつかの重要な側面があります。
Start
では、command-line arguments
を解析して、ロードするマップなどの情報を読み込みますが、最も重要なのは、どのポートをバインドするかです。
このような専用サーバーを実行する場合、2つのメインポートを使用します。(i)新しいプレイヤー接続をリッスンするサーバーポート、および(ii)A2Sクエリプロトコルを使用してサーバーからリアルタイム情報を取得するために使用されるクエリポート。
Gameye
でサーバーをホストする場合、Igniter(github)というツールを使用します。
このツールは、ゲームサーバーの現在の状態を追跡し、サービスマネージャーに報告します。
Igniter
と通信するには、いくつかの特定の文字列をstdout
ストリームに出力する必要があります(次のセクションでこれらのメッセージについて詳しく説明します)。そのために、それらのキー文字列を記録するGameyeIgniterApi
を作成しました。
たとえば、 starting
、playing
、または exiting
などの状態を公開するために、GameyeServer
スクリプトによって使用されます。
GameyeServer
スクリプトのもう1つの重要な側面は、A2SManager
クラスの使用です。
このマネージャーは、サーバーに関する内部メタデータを更新します。
この情報は、後でクライアントがサーバー構成をチェックするために使用します。
また、例として、このスクリプトは、セッションに接続しているプレーヤーがいない場合にゲームサーバーを自動的にシャットダウンします。
そのため、ゲームサーバーを起動し、プレイヤーが参加するのを待って、必要なだけプレイできるようにします。最後のプレイヤーが切断すると、自動的にシャットダウンします。
そのため、ゲームサーバーを起動し、プレイヤーが参加するのを待って、必要なだけプレイできるようにします。最後のプレイヤーが切断すると、自動的にシャットダウンします。
GameyeInGame
シーンについては、現時点では単なるプレースホルダーであり、実際のコンテンツやゲームプレイはありません。サーバーとクライアントが別のシーンをプレイできるようにするためだけに使用します。
サーバーで発生することへの説明は以上です。ビルドしてみましょう。
Build Settings
ウィンドウを開き、インデックス0
にGameyeHeadlessServer
を、インデックス1
にGameyeInGame
シーンを含めます。- Bolt(
Bolt / Compile Assembly
)を再コンパイルして、シーンの構成を認識できるようにしてください。 Architecture``x86
を使用して、Target Platform
をLinux
に変更します。- ゲームをビルドします。ここではこの名前を使用するため、バイナリには
game.x86
という名前を付けることをお勧めします。
ゲームサーバーのDockerイメージを構築する
Gameye
サービスの主な特徴の1つは、ゲームの実行可能ファイルの構築方法に依存しないことです。 Docker Image
への参照が必要なだけで、必要な数のサーバーをスピンできます。
ただし、この image
にはいくつかの設定が必要であり、前述したIgniter
ツールを使用する必要があります。
Igniter
はゲームを実行(点火)し、実行可能ファイルを制御します。
これをできるだけスムーズにするために、わずか数ステップでDocker Image
を構築するために使用できるテンプレートを構築しました。
https://github.com/BoltEngine/gameye_bolt_server_imageにあるプロジェクトのクローンを作成してください。
リポジトリにはすでにイメージの構築方法の説明が含まれていますが、ここで要約します。
- リポジトリをマシンにダウンロードします。
- Game Serverバイナリをビルドします(これは最後のステップで行いました)。
- サーバーファイルを
build
フォルダー、実行可能ファイル、データフォルダーにコピーします。 実行可能ファイルの名前はgame.x86
に設定しました。 Makefile
ファイルを開き、変数DOCKER_USERNAME
(DockerHub
ユーザー名)とGAME_IMAGE_NAME
(DockerHub
リポジトリ名)を変更します。- フォルダーで
make
を実行してイメージをビルドします。
これで、アップロード用のDocker Image
が設定されました。
この画像と Gameye
サービスを使用するときに注意する必要がある設定について説明します。
Docker
側から始めます。ルートフォルダーに Dockerfile
があります。
この構成ファイルは、イメージの構築方法を説明しています。主な点は次のとおりです。
- 画像は
ubuntu:latest
に基づいています。そのため、UnityプロジェクトをLinux
実行可能ファイルとしてビルドしました。 これは、Gameye
でゲームを実行するための推奨OSです。 - それはいくつかの環境変数を定義します。それらはビルド中に特定のフォルダーにいくつかのファイルを割り当てるために使用されます。たとえば、ゲームのバイナリを
GE_DIRGAME
に入れます。README.md
ファイルはそれらすべての変数を記述します。 - 最後に、画像が
docker-entrypoint.sh
をENTRYPOINT
として実行する必要があることをDocker
に通知します。このファイルは特定のパラメーターを指定して、Igniter-shell
(Igniter
ツールから実行可能)を実行するだけです。使用方法については、公式ページをご覧ください。
では、 Gameye
関連のファイルについて説明します。
サービスドキュメントで説明した通り、2つの構成ファイル、(i) args.yaml
および(ii)config.yaml
が必要です。
ゲームサーバーがオーケストレーションシステムと連携するためには、これらのファイルにいくつかの詳細な値が必要です。
今回のケースでは、args.yaml
ファイルはarg/main.yaml
にあり、外部と通信するためにサーバーに開く必要があるすべての必要なポートを登録します。
ご覧のとおり、(i) server
(ゲームサーバーポート)、(ii)query
( A2S
クエリ用)、(iii)すべてのPhoton関連ポート(マッチメイキングとしてPhotonを使用する予定の場合)。
このファイルを、以前に連絡した のGameye
アカウントマネージャーに送信して設定してもらいます。
同様に、 config/main.yaml
ファイルにあるconfig.yaml
ファイルがあります。
args
ファイルとconfig
ファイルは同じ名前(この場合は main.yaml
)を使用する必要があるため、これらは独自のディレクトリにあります。
設定ファイルはもう少し広範です:
cmd
:ここでは、サーバーに送信されるコマンドライン引数について説明します。 したがって、ヘッドレスモードでゲームを開始し(-batchmode -nographics -logFile
)、必要なポート情報を引数として渡します(-port ${port.server} -query ${port.query}
)。Igniter
は、動的な値を適切な値に置き換えます。script
:このセクションでは、ゲームサーバーが実行できるすべての状態と遷移について説明します。前に説明したキー文字列
を構成します。ご覧のように、Igniter
はplaying
状態に変更するときにGAMEYE STATE CHANGE PLAY
などのいくつかの値を期待します。すべてのパラメータはGameye
ページに文書化されています。defaults
:最後に、引数にいくつかのデフォルト値を設定します。
テンプレートの動作の基本は以上です。必要な変更を加える準備が整いました。
Docker Image
をアップロードする前に、Docker
リポジトリへの Gameye
アクセスをセットアップし、プッシュWebhookを設定して、バイナリの新しいバージョンをいつアップロードするかをサービスが認識できるようにする必要があります。
詳細は、 Gameye
ドキュメントページで説明しています。Sending a build notification
および Image Permissions
セクションを探してください。
Gameye
アカウントマネージャーが手助けをしてくれます。
準備がすべて整ったので、 make upload
コマンドを実行して画像をDockerHub
にアップロードするか、 docker push username/image_name:version
を使用して手動で実行します。
ほんの数分で、使用できるようになります。
サーバーの展開を確認する
デプロイが成功したことを確認する簡単な方法の1つは、 Gameye
REST APIを使用して新しいサーバーをリクエストし、そこにあるかどうかを確認することです。
REST APIに関するドキュメントは、このリンクにあります。
次に、 Gameye Application Token
を使用します。この情報は、Gameye
スタッフから送信されました。
すべての{key}
を「トークン」の文字列に置き換えます。
最初に、次のコマンドを実行して、既に実行されているサーバー(存在するべきではありません)があるかどうかを確認する必要があります。
bash
curl --request GET \
--url https://api.gameye.com/fetch/match \
--header 'authorization: Bearer {key}'
実行中のサーバーがないことを示す、以下のような応答が得られます。
JSON
{
"match": {}
}
ゲームサーバーをリクエストするために、次のように、別のAPIエンドポイントを使用します。
bash
curl --request POST \
--url https://api.gameye.com/action/start-match \
--header 'authorization: Bearer {key}' \
--header 'content-type: application/json' \
--data '{"locationKeys":["{locationKeys}"],"matchKey":"{name}","gameKey":"{gameKey}","templateKey":"{templateKey}","endCallbackUrl":"{endCallbackUrl}"}'
この呼び出しに関する備考:
locationKeys
: 利用可能なリージョンのリストはこちらです。matchKey
: 新しいリクエストを行うたびに一意のIDである必要があります。 重複したキーを使用すると、サーバーが存在しなくてもエラーが発生します。gameKey
: このキーは起動するサーバーを表し、Gameye
のスタッフによって修正および設計されています。 また、使用するキーも通知されます。templateKey
: テンプレートの値は、args.yaml
とconfig.yaml
に使用したファイルの名前と一致している必要があります。 このサンプルでは、これらのファイルの名前としてmain.yaml
を使用しているため、この引数に文字列"main"
を渡す必要があります。endCallbackUrl
:これはマッチが終了したときに呼び出されるWebhookです。 サーバーからいくつかの統計を取得するのに役立ちます。
適切なパラメータでリクエストを行うと、次のような結果が得られます。
JSON
{
"id": "bfc5890f-9ba2-46ef-bb69-31ac5cf6a092",
"image": "boltgameimage",
"location": "washington_dc",
"host": "123.456.789.000",
"created": 1590002692454,
"port": {
"server": 53723,
"query": 51642,
"masterServer1": 55488,
"masterServer2": 49784,
"gameServer1": 62047,
"gameServer2": 50203,
"nameServer1": 57337,
"nameServer2": 61128
}
}
新しいゲームサーバーが正常に展開され、一部のプレイヤーの準備が整ったことを示しています。
ご覧のとおり、 args.yaml
ファイルで尋ねたように、パブリックIPとリスニングポートに関する情報があります。
これでこのサーバーをシャットダウンできます。
次の呼び出しを使用して、 Gameye
にセッションの停止を要求します。
bash
curl --request POST \
--url https://api.gameye.com/action/stop-match \
--header 'authorization: Bearer {key}' \
--header 'content-type: application/json' \
--data '{"matchKey":"example-match"}'
ご覧のとおり、どのセッションが強制終了されるかを通知するためには matchKey
のみを使用します。
このリクエストに対する返信はありません。
ゲームクライアントの詳細
サーバーが機能するようになったので、サーバーに接続するクライアントが必要です。
このセクションでは、私たちが構築したクライアントサンプルについて説明します。そこから始めて、ニーズに合わせて拡張できます。
前に述べたように、 samples_pro
内の GameyeIntegration
フォルダーを再度確認すると、 GameyeClient
シーンが見つかります。
これがプレイヤーの出発点になります。
要約すると、プレイヤーは単純化されたロビーシーンを利用します。ロビーシーンでは、利用可能なすべてのゲームサーバーを表示できますが、REST APIを使用して行ったように、サーバーが見つからない場合は新しいサーバーをリクエストできます。
プレイヤーのUIは非常にシンプルで、2つの主要な部分で構成されています。(i)Request New Server
ボタンのあるNo Server Found
パネルと、(ii)サーバーのリストを表示するロビーリストです。
これは、 GameyeUIManager
クラスによって管理され、イベントを使用してサーバーリクエストをトリガーし(クラスのrequestServerEvt
アクションを参照)、サービスから取得したデータをサーバーのリストに入力します(詳細は次を参照)。
また、 GameyeUIServerInfoManager
クラスがあります。これはサーバーリストのアイテムを表し、UIコンテンツを取り込み、Join
ボタンのクリックに応答します。
ゲームクライアントのコアセクションは次のクラスです。
GameyeApi
ここでは、 Gameye
のドキュメントに記載されているREST APIに基づいたシンプルなHTTPクライアントを実装しました。
APIを使用する場合は両方のタイプが必要なので、GET
とPOST
リクエストを実行できます。
このサンプルでは、次のメソッドで表される2種類のリクエストのみを使用します。
RequestServer
: この関数を呼び出すことにより、Gameye
にいくつかの事前定義された値で新しいゲームサーバーを起動するように要求します。この操作の結果は、引数として渡されたアクションコールバックで受信されます。GetSessionList
: このメソッドは、有効なゲームサーバーの現在のリストを要求し、それらの情報をマネージ形式に解析します。これのクラス定義は、GameyeData.cs
ファイルにあります。
GameyeClientManager
これは、プレイヤー管理の中心的なクラスであり、すでに説明されている他のすべてのパーツを統合し、それらを連携させる役割を果たします。
このクラスは、次のタスクを実行できます。
- APIを使用して
Gameye
サービスから情報をリクエストし、処理されたデータをUIに入力して、有効なサーバーのリストを更新します。これは、refreshInterval
値(UpdateSessions
メソッド)に基づいて定期的に発生します。 - UI入力に基づいて新しいゲームサーバーの作成をリクエストします(
RequestServer
メソッド)。 - Boltクライアントを起動し、リモートゲームサーバーに接続します(
JoinSession
メソッド)。
すべてのメソッドの詳細はドキュメント化されています。
ゲームクライアントを実行する
可動部分がどのように連携するかについての理解が深まったところで、専用サーバーに接続するようにクライアントを構成してみましょう。
Unityクライアントは、サーバーと同様、2つのシーンで構成されています。(i) GameyeClient
は前のセクションで説明したメニューシーンです (ii) GameyeInGame
は同じゲーム内シーンであり、単なるプレースホルダーです。
次の手順に従ってゲームクライアントを実行します。
GameyeClient
シーンを開きます。 シーンにGameyeClient
という名前のゲームオブジェクトが表示されます。インスペクターで開きます。 これにはGameyeClientManager
コンポーネントがあり、Gameye Application Token
を設定する必要があります。プレハブの変更を適用してシーンを保存できます。Build Settings
ウィンドウを開き、インデックス0
のGameyeClient
とインデックス1
のGameyeInGame
でシーンリストを設定します。- Bolt(
Bolt/Compile Assembly
)を再コンパイルして、シーンの構成を認識できるようにしてください。 - これからは、エディターでクライアントを実行するか、スタンドアロンバージョンをビルドできます。
クライアントが実行されている状態で、Request New Server
ボタンがデフォルトで30 secs
無効になっていることがわかります。
これは、新しいサーバーをリクエストする前に、実行中のサーバーがないことを確認するためです。
サーバーのリストはデフォルトで20 secs
ごとに更新されます。"Refresh Interval"スライダーを動かすことでこれを変更できます。
Gameye
には1分あたりのAPIリクエストの制限があるため、妥当な値にしておくことをお勧めします。
サーバーが利用できない場合は、リクエストボタンをクリックするだけで、非同期リクエストが実行されます。
すべてが順調に進んでいると、コンソールログにJSON
応答が表示され、数秒以内に(別の更新更新後)、セッションがロビーリストにポップアップ表示されます。
サーバー名、現在読み込まれているマップ、プレイヤーの数/プレイヤーの最大数、作成時間などの一部のサーバー情報が表示されます。
すべての追加情報は、 A2Sサーバークエリ
APIを通じて利用できます。
このサーバーに接続するには、Join
ボタンをクリックするだけです。
クライアントが接続し、ゲーム内シーンを読み込みます。
そこから、サンプルコードの基本的な機能を拡張して、セッションをフィルタリングしたり、サーバーに関する詳細情報を表示したり、特定のゲームサーバータイプを要求したりすることができます(これは、名前や値が異なる複数の config.yaml
ファイルを使用して行われます。 また、サーザーを要求する際に正しい templateKey
を使用します)。