Amazon GameLift Anywhereで自作の簡易ゲームサーバーを動かしてみる

Amazon GameLift Anywhereで自作の簡易ゲームサーバーを動かしてみる

Clock Icon2024.12.13

こんにちは、ゲームソリューション部の入井です。

本記事はゲーソル・ギョーソル Advent Calendar 2024の13日目の記事です。

https://dev.classmethod.jp/referencecat/gamesol-businesssol-advent-calendar-2024/

https://qiita.com/advent-calendar/2024/gamesol-businesssol

今回の記事では、Amazon GameLiftの機能の1つであるAmazon GameLift Anywhereを使い、自作の簡易ゲームサーバーをGameLiftと連携させた検証の結果を書いていきます。

検証環境

  • macOS Sonoma 14.5
  • GameLiftServerSdk C++ 5.2.0
  • cmake 3.31.0

簡易ゲームサーバーを自作した背景

Amazon GameLiftは、マネジメントコンソール上でサンプルゲームを提供しています。画面上のボタンをクリックするだけであらかじめ用意されたゲームビルドを使ってフリートが立ち上がるようになっており、また作成したフリートにアクセス可能なゲームクライアントも提供されているので、これを使用することでどのようにGameLift上でオンラインゲームが動作するのかを学ぶことができるようになっています。

スクリーンショット 2024-12-08 15.00.03

GameLiftの動く様子を手軽に確認できるという意味では役に立つものですが、中身のコードが公開されていないという点で私は物足りなさを感じていました。GameLiftを本格的に触ろうとする場合、やはり手元で色々とコードをいじって、その結果どのように動作に違いが生じるのかを検証したくなります。

GitHubなどを探すと公式非公式問わずサンプルゲームのコードが公開されていますが、私が見た限りではどれもそこそこ複雑そうなプロジェクトでした。私としては、とりあえずサクッと動かしてGameLiftの動作を検証できれば良かったので、あまり重そうなプロジェクトを触るのは、学習コストや不具合発生時の原因特定の難易度などから抵抗がありました。

そこで、今回はGameLiftと連携する検証環境としての簡易ゲームサーバーを自分で作ってみました。

https://github.com/iridon0920/amazon-gamelift-light-testing

言語はC++を使っています。昨今の風潮を考えると、公式プラグインを活用してUnreal EngineやUnityといったゲームエンジン用の検証環境を作った方がより実践的ですが、目的としてはGameLiftの様々な機能を検証するシンプルな環境作りであり、ゲームエンジンを絡ませると環境が複雑になりすぎるため、今回は普通のC++環境上で開発をしました。
SDKはC++の他にC#, Go言語用のものも公開されていますが、ゲームサーバー開発でよく使われているC++で作ることにしました。
(余談ですが、C++に触れるのは大学以来だったため、GameLift云々より言語の基本的な使い方で詰まる場面が多かったです)

Amazon GameLift Anywhereとは

今回の検証環境としては、手元でサクッとGameLiftと連携できれば良かったので、Amazon GameLift Anywhereを選択しました。

通常、Amazon GameLiftではゲームフリートというリソースを作成し、その中で稼働するEC2インスタンス内でゲームサーバーを実行しますが、Amazon GameLift Anywhereを使うことで、EC2インスタンスではなくローカルやオンプレミス環境で動作しているゲームサーバーをGameLiftと連携させることができます。

2022-gamelift-anywhere-0
Amazon GameLift Anywhere のご紹介 — ゲームサーバーを独自のインフラストラクチャで実行 | Amazon Web Services ブログより引用

クラウド上のインスタンスはゲームの本番運用時は大変便利なのですが、新しいバージョンのビルドを乗せた環境の準備が完了するまでに時間がかかり、何度もビルドを修正する必要がある開発フェーズではインスタンス起動までの待ち時間を煩わしく感じることがあります。

Amazon GameLift Anywhereはそういった開発フェーズ時に便利な機能で、ゲームサーバーの更新が必要な際もローカルやオンプレミス上の起動中のマシンで新しいビルドを起動し直せば良いだけなので、クラウド上のインスタンスを使用するときのような環境作成やインスタンス起動までの待ち時間は生じません。それでいて、SDKを通してGameLiftと連携できるため、ほぼ本番運用に近い状態でゲームサーバーのデバッグが可能となります。

また、開発フェーズだけでなく本番運用時でも、上の図にも書かれているように通常のフリートとキューを介して連携することで、クラウドとオンプレミスのハイブリッド構成を取ることが可能になっています。

作成したゲームサーバー

全体の処理の流れ

実行ファイルを起動すると、以下のような処理を行うようになっています。

  • コマンドライン引数からGameLiftとの連携に必要なパラメータを取得
  • 取得したパラメータを使ってGameLift SDKの初期化
  • GameLiftに各種情報とともにサーバープロセスの準備が整ったことを伝達
  • HTTPサーバーを起動

普通のHTTPサーバーの機能しか無いので全然ゲームサーバーらしくないですが、あくまでGameLiftの機能を検証するためのものなので問題ありません。

また、全体的に以下の公式ハンズオンで公開されているgoのコードを参考にさせていただいています。

https://aws.amazon.com/jp/builders-flash/202308/create-multi-player-game/

main関数

処理の流れはコード中のコメントの通りです。

main.cpp
#include "GameLiftServer.h"
#include "httplib.h"
#include <iostream>
#include <string>

int main(int argc, char* argv[]) {
    // コマンドライン引数チェック
    if (argc != 7) {
        std::cerr << "Usage: " << argv[0] << " <webSocketUrl> <processId> <fleetId> <hostId> <authToken> <port>" << std::endl;
        return 1;
    }

    // コマンドライン引数から値を取得
    std::string webSocketUrl = argv[1];
    std::string processId = argv[2];
    std::string fleetId = argv[3];
    std::string hostId = argv[4];
    std::string authToken = argv[5];
    std::uint16_t port = std::stoi(argv[6]);

    // GameLift関係の処理をまとめたインスタンス生成、セットアップの実行
    GameLiftServer gameliftServer;
    gameliftServer.SetupSDK(
        webSocketUrl,
        authToken,
        fleetId,
        hostId,
        processId,
        port
        );

    // HTTPサーバーの起動
    httplib::Server svr;
    svr.Get("/", [](const httplib::Request &, httplib::Response &res) {
      res.set_content("Hello World!", "text/plain");
    });

    svr.listen("0.0.0.0", port);

    // HTTPサーバー終了後、GameLiftと連携した上でプロセス終了
    gameliftServer.DestorySDK();
}

GameLift SDKの初期化にあたっていくつかパラメータを渡す必要があり、コマンドライン引数の数がかなり多くなっています。

なお、HTTPサーバー関係の処理については、以下のC++用のHTTPサーバーライブラリを使わせていただいています。

https://github.com/yhirose/cpp-httplib

GameLiftServerクラス

GameLift SDKとのやりとりは全てこのクラスにまとめています。

以下、ヘッダファイルは省略します。こちらについても、処理の流れはコード中のコメントの通りです。

GameLiftServer.cpp
// ビルド時に標準C++ライブラリを利用することを指定
#define GAMELIFT_USE_STD 1
#include "GameLiftServer.h"

GameLiftServer::GameLiftServer() {
}

GameLiftServer::~GameLiftServer() {
}

// ゲームセッション開始時に呼び出されるコールバック関数
void GameLiftServer::OnStartGameSession(Aws::GameLift::Server::Model::GameSession gameSession) {
    std::cout << "[GameLift]Callback: OnStartGameSession" << std::endl;

    // このプロセスでプレイヤーからのアクセスを受ける準備が整ったとGameLiftへ通知
    Aws::GameLift::GenericOutcome outcome = 
        Aws::GameLift::Server::ActivateGameSession();
}

// GameLiftによるプロセス強制シャットダウン時に呼び出されるコールバック関数
void GameLiftServer::OnProcessTerminate() {
    std::cout << "[GameLift]Callback: OnProcessTerminate" << std::endl;
    // プロセスの終了をGameLiftへ通知
    Aws::GameLift::GenericOutcome outcome = 
        Aws::GameLift::Server::ProcessEnding();

    // GameLift SDKが使用していたメモリを解放
    Aws::GameLift::Server::Destroy();
}

// GameLiftによるヘルスチェック時に呼び出されるコールバック関数
bool GameLiftServer::OnHealthCheck() {
    std::cout << "[GameLift]Callback: OnHealthCheck" << std::endl;
    // 戻り値がtrueであれば正常、falseであれば異常とGameLiftが認識
    return true;
}

// ゲームセッション情報の更新時に呼び出されるコールバック関数
void GameLiftServer::OnUpdateGameSession(Aws::GameLift::Server::Model::UpdateGameSession gameSession) {
    std::cout << "[GameLift]Callback: OnUpdateGameSession" << std::endl;
}

// GameLiftセットアップ用関数
void GameLiftServer::SetupSDK(
    std::string webSocketUrl,
    std::string authToken,
    std::string fleetId,
    std::string hostId,
    std::string processId,
    std::uint16_t port
    ) {
    // コマンドライン引数で受け取ったパラメータをセット
    Aws::GameLift::Server::Model::ServerParameters serverParameters =
        Aws::GameLift::Server::Model::ServerParameters(
            webSocketUrl,
            authToken,
            fleetId,
            hostId,
            processId
        );
     // パラメータを元にGameLift SDKを初期化
    Aws::GameLift::Server::InitSDKOutcome initSdkOutcome = Aws::GameLift::Server::InitSDK(serverParameters);

    // InitSDKの結果を確認
    if (!initSdkOutcome.IsSuccess()) {
        std::cerr << "GameLift SDK initialization failed: " << initSdkOutcome.GetError().GetErrorMessage() << std::endl;
    }

    std::cout << "GameLift SDK initialized successfully." << std::endl;

    // ログ出力先設定
    Aws::GameLift::Server::LogParameters logParams({"game.log"});
    // 各種コールバック関数、設定情報をパラメータにセット
    Aws::GameLift::Server::ProcessParameters processParameters =
        Aws::GameLift::Server::ProcessParameters(
            std::bind(&GameLiftServer::OnStartGameSession, this, std::placeholders::_1),
            std::bind(&GameLiftServer::OnUpdateGameSession, this, std::placeholders::_1),
            std::bind(&GameLiftServer::OnProcessTerminate, this),
            std::bind(&GameLiftServer::OnHealthCheck, this),
            port,
            logParams
        );
    // パラメータを元にGameLiftにサーバープロセスの準備が完了したことを伝達
    Aws::GameLift::GenericOutcome outcome = Aws::GameLift::Server::ProcessReady(processParameters);

}

// SDK破棄処理用関数
void GameLiftServer::DestorySDK() {
    // プロセスの終了をGameLiftへ通知
    Aws::GameLift::GenericOutcome processEndingOutcome = Aws::GameLift::Server::ProcessEnding();

    // GameLift SDKが使用していたメモリを解放
    Aws::GameLift::Server::Destroy();

    // 終了処理失敗時はエラーとしてプログラムを終了
    if (processEndingOutcome.IsSuccess()) {
        exit(0);
    } else {
        std::cout << "ProcessEnding() failed. Error: " << processEndingOutcome.GetError().GetErrorMessage();
        exit(-1);
    }
}

initSDK()によってSDKが初期化され、ゲームサーバーとGameLift間の通信が開始します。その後、processReady()を実行することでGameLift上でこのゲームサーバーが使用できる状態だと認識される形になります。

補足:もう一つのinitSDK()

GameLift SDKには2種類のinitSDK()が用意されています。オーバーロード関数であり、1つは上で記載したように複数の引数に値を渡す必要があり、もう1つは何も値を渡さないで実行することができます。

2つのinitSDK()は、以下のようにゲームサーバーの実行環境によって使い分けます。

  • 値を渡すinitSDK()
    • GameLiftエージェントが無いGameLift Anywhereもしくはコンテナフリート環境
  • 値を渡さないinitSDK()
    • GameLiftのインスタンス上で実行する場合
    • GameLiftエージェントのあるGameLift Anywhereもしくはコンテナフリート

GameLiftエージェントとは、GameLiftとゲームサーバーの中継をしてくれる存在で、これがある環境で値を渡さないinitSDK()を使用できるのは、必要な値の取得からそれを使ったGameLiftとの連携までをエージェントが自動的にやってくれるからです。また、GameLiftのインスタンスも、エージェントが行う処理を自動的に実行してくれるため、値を渡さないinitSDK()を使うことができます。

なお、GameLiftエージェントが無い場合にinitSDK()に渡す必要のある値は、具体的には以下の通りとなります。

  • WebSocketURL
    • 以下のようなゲームサーバーとGameLift間の通信をこのWebSocketを介して行う
      • ヘルスチェック
      • ゲームセッションやプレイヤーの状態の更新
      • シャットダウンなどプロセスの制御
  • 認証トークン
    • ゲームサーバーがGameLiftと通信するために必要なトークン
  • フリートID
    • どのフリートと通信するかの指定
  • ホストID
  • プロセスID

このうち、WebSocket URL、認証トークンはGameLiftからAPI経由で取得する必要があります。具体的な取得方法については後述します。

CMake

ビルドのためのCmake設定です。(C++に慣れていないのでここで一番苦戦しました)

CmakeLists.txt
cmake_minimum_required(VERSION 3.22)
project(amazon_gamelift_light_testing)

set(CMAKE_CXX_STANDARD 20)

# 環境変数の存在確認
if(DEFINED ENV{GAMELIFT_SDK_PATH})
    set(GAMELIFT_SDK_PATH $ENV{GAMELIFT_SDK_PATH})
else()
    message(FATAL_ERROR "GAMELIFT_SDK_PATH環境変数が設定されていません。GameLift SDKのパスを設定してください。")
endif()

# パスの存在確認
if(NOT EXISTS ${GAMELIFT_SDK_PATH})
    message(FATAL_ERROR "GameLift SDKがこのパスに存在しません: ${GAMELIFT_SDK_PATH}")
endif()

include_directories(${GAMELIFT_SDK_PATH}/include)
link_directories(${GAMELIFT_SDK_PATH}/lib)

add_executable(amazon_gamelift_light_testing src/main.cpp
        src/GameLiftServer.cpp
        src/GameLiftServer.h)
target_link_libraries(amazon_gamelift_light_testing PRIVATE aws-cpp-sdk-gamelift-server)

find_package(OpenSSL REQUIRED)
target_link_libraries(amazon_gamelift_light_testing PRIVATE OpenSSL::SSL OpenSSL::Crypto)

ビルド済のGameLift SDKに対してinclude, link設定をすることで、プロジェクトからSDKを利用可能にしています。また、SDKがOpenSSLに依存しているため、そちらもプロジェクトにリンクさせています。

検証結果

ここからは、作成したゲームサーバーをGameLift Anywhereで実行するまでの流れとその結果を書いていきます。

なお、今回私が使用したゲームサーバーの実行ファイルはこちらで公開しています。実際の動作が気になる方は、こちらを使って試していただければと思います。

https://github.com/iridon0920/amazon-gamelift-light-testing/releases/tag/1.0.0

GameLift Anywhereフリートの作成

最初に、ゲームサーバーを登録するフリートを作成するために、マネジメントコンソールでGameLiftにアクセスし、Anywhere->フリートを開いて「Anywhereフリートを作成」をクリックします。

スクリーンショット 2024-12-08 16.28.29

Anywhereフリートの作成にあたって、特別な設定は不要です。今回はフリート名を「TestAnywhereFleet」としておきました。

スクリーンショット 2024-12-08 16.30.28

Anywhereフリート上でローカルやオンプレミスのゲームサーバーを動かすには、専用のロケーションを作成する必要があります。
ロケーションは、通常のフリートではap-northeast-1やus-east-1等のいわゆるリージョンを指すもので、フリート内のコンピューティングリソースがどの場所で動いているのかを表します。Anywhereフリートでは、自分のローカルやオンプレミス環境をそのロケーションの1つとして登録する必要があります。

ここでは、「local-test」として今使っているローカル環境をロケーションとして登録しています。

スクリーンショット 2024-12-08 16.30.46

Anywhereフリートでの準備

Anywhereフリートの作成が完了したら、以下のようにAWS CLIでregister-computeを使って先ほど作成した「local-test」ロケーションに今使っているローカル環境をコンピューティングリソースとして登録します。なお、この操作はCLIでしかできません。
ローカル環境なのでIPアドレスは127.0.0.1で設定していますが、もし外部公開しているオンプレミスサーバーをAnywhereフリートに登録するのであれば、ここで公開用のIPアドレスをセットすると、後でゲームクライアントがゲームセッションへアクセスする際にそのアドレスがGameLiftから公開されます。

aws gamelift register-compute --fleet-id fleet-3bc5f687-f35c-40f7-b538-c8e633714fac \
  --compute-name my-local-pc \
  --location custom-local-test \
  --ip-address 127.0.0.1
{
    "Compute": {
        "FleetId": "fleet-3bc5f687-f35c-40f7-b538-c8e633714fac",
        "FleetArn": "arn:aws:gamelift:ap-northeast-1:111111111111:fleet/fleet-3bc5f687-f35c-40f7-b538-c8e633714fac",
        "ComputeName": "my-local-pc",
        "ComputeArn": "arn:aws:gamelift:ap-northeast-1:111111111111:compute/my-local-pc",
        "IpAddress": "127.0.0.1",
        "ComputeStatus": "Active",
        "Location": "custom-local-test",
        "CreationTime": "2024-12-08T16:39:00.629000+09:00",
        "GameLiftServiceSdkEndpoint": "wss://ap-northeast-1.api.amazongamelift.com",
        "GameLiftAgentEndpoint": "wss://ap-northeast-1.process-manager-api.amazongamelift.com"
    }
}

登録が成功すると、戻り値の中にGameLiftServiceSdkEndpointとしてWebSocket URLが帰ってきます。これは、後でゲームサーバーを実行する際に使います。

続いて、ゲームサーバーがGameLiftと通信するための認証トークンを取得します。

aws gamelift get-compute-auth-token --fleet-id fleet-3bc5f687-f35c-40f7-b538-c8e633714fac \
 --compute-name my-local-pc
{
    "FleetId": "fleet-3bc5f687-f35c-40f7-b538-c8e633714fac",
    "FleetArn": "arn:aws:gamelift:ap-northeast-1:111111111111:fleet/fleet-3bc5f687-f35c-40f7-b538-c8e633714fac",
    "ComputeName": "my-local-pc",
    "ComputeArn": "arn:aws:gamelift:ap-northeast-1:111111111111:compute/my-local-pc",
    "AuthToken": "13bcfe05-5b01-424e-a5ef-75006744cf73",
    "ExpirationTimestamp": "2024-12-08T19:41:30+09:00"
}

こちらも実行に成功すると、AuthTokenとして認証トークンが帰ってきます。

ゲームサーバーの実行

ここまでで必要な準備が整ったため、いよいよゲームサーバーを実行します。

以下のように実行ファイルを起動します。引数として、WebSocket UrL, プロセスID, フリートID, ホストID, 認証トークン, ポート番号の順に値を渡しています。ポート番号については、HTTPサーバー起動時にも使用します。

./amazon_gamelift_light_testing \
  wss://ap-northeast-1.api.amazongamelift.com \
  11111 \
  fleet-3bc5f687-f35c-40f7-b538-c8e633714fac \
  my-local-pc \
  13bcfe05-5b01-424e-a5ef-75006744cf73 \
  8000

起動に成功すると以下のように実行ログが流れます。「GameLift SDK initialized successfully.」を経て、その後のヘルスチェックも成功していることが分かります。

[2024-12-08 16:46:28] [info] Initializing GameLift SDK
[2024-12-08 16:46:28] [info] Created Instance
[2024-12-08 16:46:28] [info] Initializing Networking
[2024-12-08 16:46:28] [info] Setting Up WebSocket With default callbacks
[2024-12-08 16:46:28] [info] Registering GameLift CallBack for: CreateGameSession
[2024-12-08 16:46:28] [info] Registering GameLift CallBack for: DescribePlayerSessions
[2024-12-08 16:46:28] [info] Registering GameLift CallBack for: GetComputeCertificate
[2024-12-08 16:46:28] [info] Registering GameLift CallBack for: GetFleetRoleCredentials
[2024-12-08 16:46:28] [info] Registering GameLift CallBack for: TerminateProcess
[2024-12-08 16:46:28] [info] Registering GameLift CallBack for: UpdateGameSession
[2024-12-08 16:46:28] [info] Registering GameLift CallBack for: StartMatchBackfill
[2024-12-08 16:46:28] [info] Registering GameLift CallBack for: RefreshConnection
[2024-12-08 16:46:28] [info] Connecting to GameLift WebSocket server. websocketUrl: wss://ap-northeast-1.api.amazongamelift.com, processId: 11111, hostId: my-local-pc, fleetId: fleet-3bc5f687-f35c-40f7-b538-c8e633714fac
[2024-12-08 16:46:28] [info] Opening Connection
[2024-12-08 16:46:28] [info] Attempting to perform connection
[2024-12-08 16:46:28] [info] Performing connection
[2024-12-08 16:46:28] [info] Connection request created successfully. Waiting for connection to establish...
[2024-12-08 16:46:28] [info] Connection request queued.
[2024-12-08 16:46:29] [info] Connected to WebSocket
[2024-12-08 16:46:29] [info] Connection state changed: Undefined error: 0
[2024-12-08 16:46:29] [info] Connection established successfully.
[2024-12-08 16:46:29] [info] Connection established, transitioning traffic
[2024-12-08 16:46:29] [info] Connected to endpoint
[2024-12-08 16:46:29] [info] Networking outcome success. Init SDK success
GameLift SDK initialized successfully.
[2024-12-08 16:46:29] [info] Calling ProcessReady
[2024-12-08 16:46:29] [info] Sending Socket Message, isConnected:true, endpoint: 3.163.218.15:443, host: ap-northeast-1.api.amazongamelift.com, port: 443
[2024-12-08 16:46:29] [info] Received message from websocket endpoint: 3.163.218.15:443, host: ap-northeast-1.api.amazongamelift.com, port: 443
[2024-12-08 16:46:29] [info] Deserialized Message has Action: ActivateServerProcess
[2024-12-08 16:46:29] [info] Successfully executed ActivateServerProcess. Marked m_processReady as true and starting m_healthCheckThread().
[2024-12-08 16:46:29] [info] Calling ReportHealth
[GameLift]Callback: OnHealthCheck
[2024-12-08 16:46:29] [info] Received Health Response: true from Server Process: 11111
[2024-12-08 16:46:29] [info] Trying to report process health as true for process 11111
[2024-12-08 16:46:29] [info] Sending Socket Message, isConnected:true, endpoint: 3.163.218.15:443, host: ap-northeast-1.api.amazongamelift.com, port: 443
[2024-12-08 16:46:29] [info] Received message from websocket endpoint: 3.163.218.15:443, host: ap-northeast-1.api.amazongamelift.com, port: 443
[2024-12-08 16:46:29] [info] Deserialized Message has Action: HeartbeatServerProcess
[2024-12-08 16:46:29] [info] Performing HealthCheck(), processReady is true, wait for 55808 ms for next health check
[2024-12-08 16:47:25] [info] Calling ReportHealth
[GameLift]Callback: OnHealthCheck
[2024-12-08 16:47:25] [info] Received Health Response: true from Server Process: 11111
[2024-12-08 16:47:25] [info] Trying to report process health as true for process 11111
[2024-12-08 16:47:25] [info] Sending Socket Message, isConnected:true, endpoint: 3.163.218.15:443, host: ap-northeast-1.api.amazongamelift.com, port: 443
[2024-12-08 16:47:25] [info] Received message from websocket endpoint: 3.163.218.15:443, host: ap-northeast-1.api.amazongamelift.com, port: 443
[2024-12-08 16:47:25] [info] Deserialized Message has Action: HeartbeatServerProcess
[2024-12-08 16:47:25] [info] Performing HealthCheck(), processReady is true, wait for 51062 ms for next health check

ゲームサーバー起動後、マネジメントコンソールでAnywhereフリートのメトリクスを確認すると、以下のようにプロセスが増えています。これにより、起動したゲームサーバープロセスがGameLift側でも認識されていることが確認できます。

スクリーンショット 2024-12-08 17.01.14

ゲームセッションの作成

ローカルのゲームサーバープロセスがGameLift上で無事に連携できているため、このままゲームセッションを作成してみます。ゲームセッションとは、プレイヤーが遊ぶための場所のようなもので、ゲームサーバーに紐付けてGameLift上で管理されます。

以下のように、create-game-sessionにより特定のロケーション向けにゲームセッション作成リクエストを飛ばせます。--maximum-player-session-countオプションは、その名の通り対象のゲームセッションにアクセスできる最大プレイヤー数ですが、今回は色々なプレイヤーをアクセスさせるわけではないので1にしています。

aws gamelift create-game-session --fleet-id fleet-3bc5f687-f35c-40f7-b538-c8e633714fac --location custom-local-test --maximum-player-session-count 1 
{
    "GameSession": {
        "GameSessionId": "arn:aws:gamelift:ap-northeast-1::gamesession/fleet-3bc5f687-f35c-40f7-b538-c8e633714fac/custom-local-test/gsess-c0b157f8-313e-4eda-9f20-8d1312bc90f0",
        "FleetId": "fleet-3bc5f687-f35c-40f7-b538-c8e633714fac",
        "FleetArn": "arn:aws:gamelift:ap-northeast-1:111111111111:fleet/fleet-3bc5f687-f35c-40f7-b538-c8e633714fac",
        "CreationTime": "2024-12-08T16:50:02.745000+09:00",
        "CurrentPlayerSessionCount": 0,
        "MaximumPlayerSessionCount": 1,
        "Status": "ACTIVATING",
        "GameProperties": [],
        "IpAddress": "127.0.0.1",
        "Port": 8000,
        "PlayerSessionCreationPolicy": "ACCEPT_ALL",
        "Location": "custom-local-test"
    }
}

実行に成功すると、作成されたゲームセッションの情報とともにサーバー情報も取得できます。IPアドレスやポート番号などが、先ほど指定したものと同じになっていることが確認できます。

ゲームセッション作成リクエストと同時に、OnStartGameSession()コールバックが実行され、ゲームサーバー側の実行ログに以下のように表示されます。

[GameLift]Callback: OnStartGameSession
[2024-12-08 16:50:02] [info] Sending Socket Message, isConnected:true, endpoint: 3.163.218.15:443, host: ap-northeast-1.api.amazongamelift.com, port: 443
[2024-12-08 16:50:03] [info] Received message from websocket endpoint: 3.163.218.15:443, host: ap-northeast-1.api.amazongamelift.com, port: 443
[2024-12-08 16:50:03] [info] Deserialized Message has Action: ActivateGameSession

GameLift側のメトリクスでは、アクティブインスタンス数が1になったまま、アイドル状態のインスタンスが0に変わりました。これは、ゲームセッションが作成されたことで、インスタンス内の待機状態のプロセスが無くなったためです。

スクリーンショット 2024-12-08 16.58.37

また、アクティブなゲームセッションメトリクスが1に上がっています。

スクリーンショット 2024-12-08 16.58.51

ここまで来たら、あとはゲームクライアントからゲームセッションへアクセスすれば、ゲームが開始できます。

なお、今回の主旨からは外れますが、起動したサーバーに対し以下のようにcurlコマンドを打つと、ちゃんとレスポンスが得られるようになっています。

curl 0.0.0.0:8000
Hello World!

さいごに

GameLift Anywhereを活用し、GameLiftと連携できる軽量な検証用ゲームサーバー環境を作成してみました。

この環境があることで、他にも色々なGameLiftの機能を検証することが可能になりました。検証した結果については、今後もブログで書いていく予定です。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.