ゲーム サーバーおよび PlayFab との統合のローカルでのデバッグ
概要
PlayFab マルチプレイヤー ゲーム サーバーは PlayFab ゲーム サーバー SDK (GSDK) と統合する必要があります。 また、ゲーム サーバーは PlayFab マルチプレイヤー プラットフォーム上でコンテナー化アプリケーションとして実行されます。
ゲーム サーバーをコンテナー化アプリケーションとして実行することで、Azure での PlayFab プラットフォームの環境に適合する環境でサーバーをローカルで実行およびデバッグできるようになります。 そうすることにより、高速な開発の繰り返しが容易になります。 この記事は、PlayFab ゲーム サーバーがプラットフォームの要件に準拠していることを確認するのに役立ちます。
PlayFab のローカル デバッグ ツールセットには、GSDK への疑似応答を提供してゲーム サーバーが GSDK に正しく統合されているかどうかを確認する、LocalMultiplayerAgent が含まれています。 疑似応答を使用して、VmAgent は PlayFab マルチプレイヤー プラットフォーム上でゲーム サーバーのライフサイクルでのさまざまな状態を繰り返します。
コンテナー化されたアプリケーションとしてゲーム サーバーを実行するようにエージェントを構成できます。 ゲーム サーバーが必要なすべての依存関係と共にパッケージ化され、PlayFab マルチプレイヤー プラットフォームで問題なく実行されることを確認します。 LocalMultiplayerAgent は、Windows または Linux のゲーム サーバーで動作します。
基本設定 - Windows
ゲーム サーバーを GSDK と統合してビルドします。 詳細については、「ゲーム サーバーの PlayFab ゲーム サーバー SDK (GSDK) との統合」を参照してください。
ゲーム サーバーとその依存関係を zip アーカイブに圧縮します。 コンテナー モードで正しく実行するには、コンテナー イメージに含まれていないシステム DLL が zip アーカイブに含まれている必要があります。 詳細については、「必須システム DLL を決定する」を参照してください。
注意
zip ファイル内のフォルダー内のフォルダーを誤って zip 圧縮するという、よくある間違いに注意してください。 zip 圧縮した後に zip フォルダーを参照して、圧縮ソフトウェアによってファイル階層に余分なレイヤーが追加されていないことを再確認します。
ローカル デバッグ ツールセットをダウンロードして、任意のフォルダー (例: C:\PlayFabVmAgent) に展開します。
LocalMultiplayerAgent MultiplayerSettings.json Generator json ファイルの検査中に、以下のオプションについての詳細をご確認ください。
抽出したフォルダーの場所に移動し、MultiplayerSettings.json ファイルをテキストエディター (Visual Studio Code など) で開きます。 次のプロパティを更新します。
-
LocalFilePath
- 作成しておいたゲーム サーバー アセットの zip ファイルの (ワークステーション上の) 完全なローカル パス。たとえば、D:\\MyAmazingGame\\asset.zip (JSON フォーマットではバックスラッシュをエスケープする必要があります)。 -
StartGameCommand
- コンテナー内で実行可能なゲーム サーバーへの完全パス。 例えば、実行可能ファイル名が mygame.exe であれば、サンプル パスは C:\\Assets\\mygame.exe になります。 StartGameCommand のパスは、プロセスとコンテナーで異なります。 コンテナーの StartGameCommand パスは、コンテナーまたはアセット フォルダ内のリソースへの絶対パスです。 プロセスの StartGameCommand パスは、作業ディレクトリが最初に指定されるアセットとなる相対パスです。 -
PortMappingsList
- これらは、実行中にゲームで使用できるポートです。NodePort
はワークステーションで開かれているポートで、GamePort.Number
は、コンテナーで実行するときにゲームサーバーがバインドする必要のあるポートです。 PortMappingsList: ゲーム サーバーがクライアントをリッスンしているプロトコルとポートに一致するように GamePort セクションを更新します。 ゲームサーバーに複数のポートが必要な場合は、既存のポート構成をコピーして貼り付け、NodePort
をインクリメントしてから、GamePort.Number
とGamePort.Name
を必要なポートに更新します。 プロセスとして実行する場合、GamePort.Number
は無視されます。プロセスは NodePort にバインドする必要があります。 両方のケースを処理するには、次のいずれかを実行します。- ポートを同じ値に設定する
- 実行時に GSDK 構成で、バインドする正しいポートを常に返すキー
GamePort.Name
の値を確認してください。
-
MultiplayerSettings.json ファイルには、編集したい追加のフィールドがあります。
-
ResourceLimits
(オプション) - 指定されている場合、docker は CPU 使用量またはメモリ使用量を制限します。 警告: サーバーが許可されたメモリを超えると、サーバーは強制終了されます。 ResourceLimits は、コンテナー モードでのみ指定できます。 -
SessionCookie
(オプション) - RequestMultiplayerServer API 呼び出しの一部としてゲーム サーバーに渡されるセッション Cookie。 -
OutputFolder
(オプション) - 出力ファイルと構成ファイルの生成先となるドライブまたはフォルダーの絶対パス。 ゲームサーバーはこのパスの下に抽出されるため、利用可能な十分なスペースがあることを確認してください。 指定しない場合は、エージェント フォルダが使用されます。 -
MountPath
- アセットをマウントするコンテナー内のパス。 プロセス モードで実行する場合、このフィールドを指定する必要はありません。 サンプル値 - C:\\Assets を使用することをお勧めします (JSON フォーマットではバックスラッシュをエスケープする必要があります)。 -
AgentListeningPort
- ゲーム サーバーと通信するためにエージェントがバインドするポートを指定します。 56001 にバインドしている別のプロセスがある場合は、この値を変更する (または他のプロセスを強制終了する) 必要があります。
-
GSDK との統合の検証
-
MultiplayerSettings.json ファイルで、
RunContainer
をfalse
に設定します。 - PowerShell ウィンドウ (管理者として実行) で以下の操作を行います。
- 作業ディレクトリを、ツールセットの展開先フォルダーに変更します。
- LocalMultiplayerAgent.exe 実行します。 この時点で、LocalMultiplayerAgent は http リスナーを設定し、ゲームアセットを解凍し、別のプロセスでゲーム サーバーを起動します。 次に、LocalMultiplayerAgent は、ゲーム サーバーに統合された GSDK からのハートビートを待ちます。
- GSDK が正しく統合されている場合、LocalMultiplayerAgent は次の出力を出力します。
-
CurrentGameState - Initializing
(これはオプションであり、ゲームサーバーが直接GSDK::ReadyForPlayers
を呼び出し、GSDK::Start
を呼び出さない場合は表示されない場合があります) CurrentGameState - StandingBy
CurrentGameState - Active
CurrentGameState - Terminating
-
- シャットダウン コールバックが正しく設定されている場合、状態が終了に設定された直後にゲーム サーバーが終了します。 PlayFab プラットフォームで不正なシャットダウンを避けるために、ゲーム サーバーが終了していることを確認することが重要です。
- ゲームが終了すると LocalMultiplayerAgent も終了します。
ゲームへの接続のテスト
ゲーム サーバーの実行可能ファイルが実行されていて、LocalMultiplayerAgent が CurrentGameState - Active
を出力すると、IP アドレス 127.0.0.1 とゲーム サーバーがリッスンしているポート NodePort
を使用してゲームサーバーに接続できます。
NumHeartBeatsForActivateResponse
ハートビートの後、LocalMultiplayerAgent はゲーム サーバーにスタンバイからアクティブに移行するように要求します。
NumHeartBeatsForTerminateResponse
ハートビートの後、LocalMultiplayerAgent はゲーム サーバーにアクティブから終了に移行するように要求します。 この動作は、MultiplayerSettings.json ファイルの値を更新することで調整できます。
コンテナー化の確認
コンテナーの世界に慣れていない場合は、ここでイントロを確認できます。
前提条件
- April 2018 (1803) Update 以降の Windows 10 Pro。
- Docker をダウンロードします。 または、Docker Web サイトのメイン ページからダウンロードすることもできます。
セットアップ
- Docker で [Windows コンテナーを使用] が設定されていることを確認します。
- PowerShell ウィンドウ (管理者として実行) で以下の操作を行います。
- ツールセットの展開先フォルダーに移動します。
- Docker ネットワークを設定する Setup.ps1 を実行し、LocalMultiplayerAgent と通信するためのファイアウォール ルールを追加し、Microsoft/PlayFab-Multiplayer から PlayFab docker イメージをプルダウンします。 スクリプトを初めて実行するときは、コンテナー イメージのダウンロードに数分かかる場合があります。
注意
このセットアップを正常に実行するには、インストールされているサード パーティー製ウイルス対策プログラム (McAfee、Norton、Avira など) のファイアウォールの構成変更が必要になることがあります。
コンテナー内でのゲーム サーバーの実行
-
MultiplayerSettings.json ファイルで、
RunContainer
をtrue
に設定します。 - ツールセットの展開先フォルダー (C:\PlayFabVmAgent) で Powershell ウィンドウ (管理者として実行) を開いて、
LocalMultiplayerAgent.exe
を実行します。 これにより、コンテナー内でゲーム サーバーが起動します。 しばらくすると、ゲーム状態が変化したことが Powershell ウィンドウに出力されます (上記の「GSDK との統合の検証」と同様)。
コンテナー内で実行されているゲーム サーバーへの接続のテスト
LocalMultiplayerAgent の出力がCurrentGameState - Active
を出力する場合、IP アドレス 127.0.0.1 と、MultiplayerSettings.json ファイルで指定されている NodePort
(既定では 56100) に等しいポートを使用してゲーム サーバーに接続します。
NumHeartBeatsForActivateResponse
ハートビートの後、LocalMultiplayerAgent はゲーム サーバーにスタンバイからアクティブに移行するように要求します。
NumHeartBeatsForTerminateResponse
ハートビートの後、LocalMultiplayerAgent はゲーム サーバーにアクティブから終了に移行するように要求します。 この動作は、MultiplayerSettings.json ファイルの値を更新することで調整できます。
Linux コンテナーでの LocalMultiplayerAgent の使用
LocalMultiplayerAgent で、Docker for Windows を使用して Windows のコンテナーで実行することにより、Linux ゲーム サーバーをデバッグできます。 Windows での Linux コンテナーの実行の詳細については、こちら をご覧ください。 本質的には、-lcow パラメーターを使用してエージェントを実行し、LocalMultiplayerSettings.json ファイルを適切に構成するだけです。
コンテナー化された Linux ゲーム サーバーを Windows で実行するには、次の手順を実行する必要があります。
- GitHub のリリース ページから LocalMultiplayerAgent の最新バージョンをダウンロードします
- Windows で Docker Desktop をインストールします。
- Linux コンテナー で実行されていることを確認してください
- ハード ドライブの 1 つをマウントする必要があります。手順については、こちらをご覧ください。
- ゲーム サーバー イメージは、コンテナー レジストリに公開することも、ローカルで構築することもできます。
- "PlayFab" という Docker ネットワークを作成する
SetupLinuxContainersOnWindows.ps1
PowerShell ファイルを実行する -
LocalMultiplayerSettings.json ファイルを適切に構成します。 以下に、
MultiplayerSettingsLinuxContainersOnWindowsSample.json
に含まれているサンプルを示します。
{
"RunContainer": true,
"OutputFolder": "C:\\output\\UnityServerLinux",
"NumHeartBeatsForActivateResponse": 10,
"NumHeartBeatsForTerminateResponse": 60,
"TitleId": "",
"BuildId": "00000000-0000-0000-0000-000000000000",
"Region": "WestUs",
"AgentListeningPort": 56001,
"ContainerStartParameters": {
"ImageDetails": {
"Registry": "mydockerregistry.io",
"ImageName": "mygame",
"ImageTag": "0.1",
"Username": "",
"Password": ""
}
},
"PortMappingsList": [
[
{
"NodePort": 56100,
"GamePort": {
"Name": "game_port",
"Number": 7777,
"Protocol": "TCP"
}
}
]
],
"SessionConfig": {
"SessionId": "ba67d671-512a-4e7d-a38c-2329ce181946",
"SessionCookie": null,
"InitialPlayers": [ "Player1", "Player2" ]
}
}
いくつか注意点があります:
RunContainer
を true に設定する必要があります。 これは、Linux ゲーム サーバーに必要です。- ゲーム サーバーの Docker イメージの詳細で
imageDetails
を変更します。 イメージは (docker build コマンドを使用して) ローカルでビルドするか、リモート コンテナー レジストリでホストすることができます。StartGameCommand
とAssetDetails
は省略可能です。 すべてのゲーム アセット + ゲーム サーバーの開始コマンドは対応する Dockerfile にパッケージ化できるため、Docker コンテナーを使用する場合は通常これらを使用しません。- 最後に、間違いなく重要なことですが、Linux コンテナーでは大文字と小文字が区別されるため、
OutputFolder
変数の大文字と小文字に注意してください。 ケーシングが間違っていると、次のような Docker 例外が表示される場合があります。マウント ソース パス の作成中にエラーが発生しました '/host_mnt/c/output/UnityServerLinux/PlayFabVmAgentOutput/2020-01-30T12-47-09/GameLogs/a94cfbb5-95a4-480f-a4af-749c2d9cf04b' mkdir /host_mnt/c/output: file exists
- 前のすべての手順を実行した後、コマンド
LocalMultiplayerAgent.exe -lcow
を使用して LocalMultiPlayerAgent を実行できます(lcow は Windows 上の Linux コンテナーを表します)
トラブルシューティング
- コンテナー モードで、ゲーム サーバーが "コンテナー...終了コード 1 で終了しました" のようなエラーですぐに終了するが、プロセス モードでは正常に機能する場合。 <必要なすべてのシステム DLL がアセット パッケージに含まれていることを確認してください。
- すべてのログは、MultiplayerSettings.json ファイルで指定されている
OutputFolder
の下にあります。 LocalMultiplayerAgent は、起動されるたびに、タイムスタンプをフォルダー名として新しいフォルダーを作成します。 ゲーム サーバーのすべてのログは GSDK 経由で出力され、GameLogs フォルダー内にあります。
ゲーム サーバーがコンテナーで実行されている場合、ディレクトリ階層のレベルが追加されてログ ファイルが振り分けられていることがあります。 - GSDK はデバッグ ログを GameLogs フォルダーに書き込みます。 これらのログは、ゲーム サーバーによって出力されたログとともに GameLogs フォルダー内にあります。
- 使用しているポートでのトラフィックを許可するようにファイアウォール (Windows や他のウイルス対策プログラム) を構成しておきます。
- 次のようなエラーが発生した場合:
Docker API responded with status code=InternalServerError, response={"message":"failed to create endpoint <container_name> on network playfab: hnsCall failed in Win32: The specified port already exists". It's likely there is already a container running on the specified port.
これは、LocalMultiplayerAgent が途中で終了した場合に発生する可能性があります。 コマンドdocker ps
を使用して実行中のコンテナーを見つけ、docker kill <container_name>
を使用してコンテナーを強制終了します。 -
Failed to find network 'playfab'
を含むエラーが発生した場合。 Setup.ps1 を再実行してみてください -
Unhandled Exception
エラーが発生した場合は、管理者として PowerShell を実行している可能性があります。 -
OutputFolder
は、他のシステム変数によって順番に使用される場合があるため、絶対パスを使用していることを確認してください。 たとえば、GSDK_CONFIG_FILE にはこのような依存関係があるため、ここで相対パス (または不正な値) を指定すると、ゲーム サーバー構成の読み込みエラーが発生する可能性があります。
既知の制限事項
- コンテナーは、デバッグの終了時に終了しない場合があります。 これが発生した場合は、管理者として次の PowerShell コマンドを実行してください。 これらのコマンドは、LocalMultiplayerAgent によって開始されなかったものを含め、すべてのコンテナーを停止して削除します。
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)