Unreal 用プラグイン: Amazon でローカルテストをセットアップする GameLift Anywhere - Amazon GameLift

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

Unreal 用プラグイン: Amazon でローカルテストをセットアップする GameLift Anywhere

このワークフローでは、Amazon GameLift 機能のクライアントとサーバーのゲームコードを追加し、プラグインを使用してローカルワークステーションをテストゲームサーバーのホストとして指定します。統合タスクが完了したら、プラグインを使用してゲームクライアントとサーバーのコンポーネントを構築します。

Amazon GameLift Anywhere ワークフローを開始するには:
  • Unreal エディタのメインツールバーで Amazon GameLift メニューを選択し、Host with Anywhere を選択します。このアクションにより [Anywhere のデプロイ] というプラグインページが開き、ゲームコンポーネントを統合、ビルド、起動するための 6 つのステップのプロセスが表示されます。

ステップ 1: プロフィールを設定する

このワークフローに従うときに使用したいプロファイルを選択します。選択したプロファイルは、ワークフローのすべてのステップに影響します。作成するすべてのリソースは、プロファイルの AWS アカウントに関連付けられ、プロファイルのデフォルト AWS リージョンに配置されます。プロファイルユーザーのアクセス許可によって、 AWS リソースとアクションへのアクセスが決まります。

  1. 使用可能なプロファイルのドロップダウンリストからプロファイルを選択します。まだプロファイルがない場合、または新しいプロファイルを作成する場合は、Amazon GameLift メニューに移動し、 AWS 「ユーザープロファイルの設定」を選択します。

  2. ブートストラップステータスが「アクティブ」でない場合は、ブートストラッププロファイルを選択し、ステータスが「アクティブ」に変わるのを待ちます。

ステップ 2: ゲームコードをセットアップする

このステップでは、クライアントとサーバーのコードに一連の更新を実施し、ホスティング機能を追加します。Unreal エディタのソースビルドバージョンをまだ設定していない場合、プラグインは手順とソースコードへのリンクを提供します。

このプラグインを使用すると、ゲームコードを統合する際にいくつかの便利な機能を活用できます。最小限の統合で基本的なホスティング機能を設定できます。より広範囲なカスタム統合を行うこともできます。このセクションでは、最小限の統合オプションについて説明します。プラグインに含まれているテストマップを使用して、クライアントの Amazon GameLift 機能をゲームプロジェクトに追加します。サーバー統合の場合は、提供されているコードサンプルを使用してプロジェクトのゲームモードを更新してください。

サーバーゲームモードを統合する

ゲームサーバーと Amazon GameLift サービス間の通信を可能にするサーバーコードをゲームに追加します。ゲームサーバーは、新しいゲームセッションを開始するなど GameLift、Amazon からのリクエストに応答できる必要があります。また、ゲームサーバーのヘルスとプレイヤー接続のステータスをレポートできる必要があります。

  1. コードエディタで、ゲームプロジェクトのソリューション (.sln) ファイルを開きます。通常はプロジェクトのルートフォルダにあります。例: GameLiftUnrealApp.sln

  2. ソリューションを開いた状態で、プロジェクトのゲームモードヘッダーファイル: [project-name]GameMode.h ファイルを探します。例: GameLiftUnrealAppGameMode.h

  3. ヘッダーファイルを次のサンプルコードに合わせて変更します。「」を独自のプロジェクト名に置き換えGameLiftServerてください。これらの更新はゲームサーバー固有のものです。クライアントで使用するために、元のゲームモードファイルのバックアップコピーを作成することをお勧めします。

    // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #pragma once #include "CoreMinimal.h" #include "GameFramework/GameModeBase.h" #include "GameLiftServerGameMode.generated.h" struct FProcessParameters; DECLARE_LOG_CATEGORY_EXTERN(GameServerLog, Log, All); UCLASS(minimalapi) class AGameLiftServerGameMode : public AGameModeBase { GENERATED_BODY() public: AGameLiftServerGameMode(); protected: virtual void BeginPlay() override; private: void InitGameLift(); private: TSharedPtr<FProcessParameters> ProcessParameters; };
  4. 関連するソースファイルの [project-name]GameMode.cpp ファイル (GameLiftUnrealAppGameMode.cpp など) を開きます。コードを次のサンプルコードに合わせて変更します。「」を独自のプロジェクト名に置き換えGameLiftUnrealAppてください。これらの更新はゲームサーバー固有のものです。クライアントで使用するために、元のファイルのバックアップコピーを作成することをお勧めします。

    次のサンプルコードは、Amazon とのサーバー統合に最低限必要な要素を追加する方法を示しています GameLift。

    • Amazon GameLift API クライアントを初期化します。サーバーパラメータを使用したInitSDK()呼び出しは、Amazon GameLift Anywhere フリートに必要です。Anywhere フリートに接続すると、プラグインはサーバーパラメータをコンソール引数として保存します。サンプルコードはランタイム時に値にアクセスできます。

    • 、、 OnStartGameSession OnProcessTerminateなど、Amazon GameLift サービスからのリクエストに応答するために必要なコールバック関数を実装しますonHealthCheck

    • 指定されたポートProcessReady()で を呼び出し、ゲームセッションをホストする準備ができたら Amazon GameLift サービスに通知します。

    // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #include "GameLiftServerGameMode.h" #include "UObject/ConstructorHelpers.h" #include "Kismet/GameplayStatics.h" #if WITH_GAMELIFT #include "GameLiftServerSDK.h" #include "GameLiftServerSDKModels.h" #endif #include "GenericPlatform/GenericPlatformOutputDevices.h" DEFINE_LOG_CATEGORY(GameServerLog); AGameLiftServerGameMode::AGameLiftServerGameMode() : ProcessParameters(nullptr) { // Set default pawn class to our Blueprinted character static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/ThirdPerson/Blueprints/BP_ThirdPersonCharacter")); if (PlayerPawnBPClass.Class != NULL) { DefaultPawnClass = PlayerPawnBPClass.Class; } UE_LOG(GameServerLog, Log, TEXT("Initializing AGameLiftServerGameMode...")); } void AGameLiftServerGameMode::BeginPlay() { Super::BeginPlay(); #if WITH_GAMELIFT InitGameLift(); #endif } void AGameLiftServerGameMode::InitGameLift() { #if WITH_GAMELIFT UE_LOG(GameServerLog, Log, TEXT("Calling InitGameLift...")); // Getting the module first. FGameLiftServerSDKModule* GameLiftSdkModule = &FModuleManager::LoadModuleChecked<FGameLiftServerSDKModule>(FName("GameLiftServerSDK")); //Define the server parameters for a GameLift Anywhere fleet. These are not needed for a GameLift managed EC2 fleet. FServerParameters ServerParametersForAnywhere; bool bIsAnywhereActive = false; if (FParse::Param(FCommandLine::Get(), TEXT("glAnywhere"))) { bIsAnywhereActive = true; } if (bIsAnywhereActive) { UE_LOG(GameServerLog, Log, TEXT("Configuring server parameters for Anywhere...")); // If GameLift Anywhere is enabled, parse command line arguments and pass them in the ServerParameters object. FString glAnywhereWebSocketUrl = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereWebSocketUrl="), glAnywhereWebSocketUrl)) { ServerParametersForAnywhere.m_webSocketUrl = TCHAR_TO_UTF8(*glAnywhereWebSocketUrl); } FString glAnywhereFleetId = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereFleetId="), glAnywhereFleetId)) { ServerParametersForAnywhere.m_fleetId = TCHAR_TO_UTF8(*glAnywhereFleetId); } FString glAnywhereProcessId = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereProcessId="), glAnywhereProcessId)) { ServerParametersForAnywhere.m_processId = TCHAR_TO_UTF8(*glAnywhereProcessId); } else { // If no ProcessId is passed as a command line argument, generate a randomized unique string. ServerParametersForAnywhere.m_processId = TCHAR_TO_UTF8( *FText::Format( FText::FromString("ProcessId_{0}"), FText::AsNumber(std::time(nullptr)) ).ToString() ); } FString glAnywhereHostId = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereHostId="), glAnywhereHostId)) { ServerParametersForAnywhere.m_hostId = TCHAR_TO_UTF8(*glAnywhereHostId); } FString glAnywhereAuthToken = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereAuthToken="), glAnywhereAuthToken)) { ServerParametersForAnywhere.m_authToken = TCHAR_TO_UTF8(*glAnywhereAuthToken); } UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_YELLOW); UE_LOG(GameServerLog, Log, TEXT(">>>> Web Socket URL: %s"), *ServerParametersForAnywhere.m_webSocketUrl); UE_LOG(GameServerLog, Log, TEXT(">>>> Fleet ID: %s"), *ServerParametersForAnywhere.m_fleetId); UE_LOG(GameServerLog, Log, TEXT(">>>> Process ID: %s"), *ServerParametersForAnywhere.m_processId); UE_LOG(GameServerLog, Log, TEXT(">>>> Host ID (Compute Name): %s"), *ServerParametersForAnywhere.m_hostId); UE_LOG(GameServerLog, Log, TEXT(">>>> Auth Token: %s"), *ServerParametersForAnywhere.m_authToken); UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_NONE); } UE_LOG(GameServerLog, Log, TEXT("Initializing the GameLift Server...")); //InitSDK will establish a local connection with GameLift's agent to enable further communication. FGameLiftGenericOutcome InitSdkOutcome = GameLiftSdkModule->InitSDK(ServerParametersForAnywhere); if (InitSdkOutcome.IsSuccess()) { UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_GREEN); UE_LOG(GameServerLog, Log, TEXT("GameLift InitSDK succeeded!")); UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_NONE); } else { UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_RED); UE_LOG(GameServerLog, Log, TEXT("ERROR: InitSDK failed : (")); FGameLiftError GameLiftError = InitSdkOutcome.GetError(); UE_LOG(GameServerLog, Log, TEXT("ERROR: %s"), *GameLiftError.m_errorMessage); UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_NONE); return; } ProcessParameters = MakeShared<FProcessParameters>(); //When a game session is created, GameLift sends an activation request to the game server and passes along the game session object containing game properties and other settings. //Here is where a game server should take action based on the game session object. //Once the game server is ready to receive incoming player connections, it should invoke GameLiftServerAPI.ActivateGameSession() ProcessParameters->OnStartGameSession.BindLambda([=](Aws::GameLift::Server::Model::GameSession InGameSession) { FString GameSessionId = FString(InGameSession.GetGameSessionId()); UE_LOG(GameServerLog, Log, TEXT("GameSession Initializing: %s"), *GameSessionId); GameLiftSdkModule->ActivateGameSession(); }); //OnProcessTerminate callback. GameLift will invoke this callback before shutting down an instance hosting this game server. //It gives this game server a chance to save its state, communicate with services, etc., before being shut down. //In this case, we simply tell GameLift we are indeed going to shutdown. ProcessParameters->OnTerminate.BindLambda([=]() { UE_LOG(GameServerLog, Log, TEXT("Game Server Process is terminating")); GameLiftSdkModule->ProcessEnding(); }); //This is the HealthCheck callback. //GameLift will invoke this callback every 60 seconds or so. //Here, a game server might want to check the health of dependencies and such. //Simply return true if healthy, false otherwise. //The game server has 60 seconds to respond with its health status. GameLift will default to 'false' if the game server doesn't respond in time. //In this case, we're always healthy! ProcessParameters->OnHealthCheck.BindLambda([]() { UE_LOG(GameServerLog, Log, TEXT("Performing Health Check")); return true; }); //GameServer.exe -port=7777 LOG=server.mylog ProcessParameters->port = FURL::UrlConfig.DefaultPort; TArray<FString> CommandLineTokens; TArray<FString> CommandLineSwitches; FCommandLine::Parse(FCommandLine::Get(), CommandLineTokens, CommandLineSwitches); for (FString SwitchStr : CommandLineSwitches) { FString Key; FString Value; if (SwitchStr.Split("=", &Key, &Value)) { if (Key.Equals("port")) { ProcessParameters->port = FCString::Atoi(*Value); } } } //Here, the game server tells GameLift where to find game session log files. //At the end of a game session, GameLift uploads everything in the specified //location and stores it in the cloud for access later. TArray<FString> Logfiles; Logfiles.Add(TEXT("GameServerLog/Saved/Logs/GameServerLog.log")); ProcessParameters->logParameters = Logfiles; //The game server calls ProcessReady() to tell GameLift it's ready to host game sessions. UE_LOG(GameServerLog, Log, TEXT("Calling Process Ready...")); FGameLiftGenericOutcome ProcessReadyOutcome = GameLiftSdkModule->ProcessReady(*ProcessParameters); if (ProcessReadyOutcome.IsSuccess()) { UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_GREEN); UE_LOG(GameServerLog, Log, TEXT("Process Ready!")); UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_NONE); } else { UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_RED); UE_LOG(GameServerLog, Log, TEXT("ERROR: Process Ready Failed!")); FGameLiftError ProcessReadyError = ProcessReadyOutcome.GetError(); UE_LOG(GameServerLog, Log, TEXT("ERROR: %s"), *ProcessReadyError.m_errorMessage); UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_NONE); } UE_LOG(GameServerLog, Log, TEXT("InitGameLift completed!")); #endif }

クライアントゲームマップを統合する

スタートアップゲームマップには、ゲームセッションをリクエストしたり、接続情報を使用してゲームセッションに接続するための基本コードが既に含まれているブループリントロジックと UI 要素が含まれています。このマップはそのまま使用することも、必要に応じて変更することもできます。スタートアップ時のゲームマップは、Unreal Engine が提供する Third Person テンプレートプロジェクトなどの他のゲームアセットと一緒に使用してください。これらのアセットはコンテンツブラウザで使用できます。プラグインのデプロイワークフローをテストしたり、ゲームのカスタムバックエンドサービスを作成するためのガイドとして使用できます。

このスタートアップマップには以下の特徴があります。

  • Anywhere フリートとマネージド EC2 フリートの両方のロジックが含まれています。クライアントを実行するときに、どちらかのフリートに接続することを選択できます。

  • クライアント機能には、ゲームセッションの検索 (SearchGameSessions())、新しいゲームセッションの作成 (CreateGameSession())、ゲームセッションの直接参加が含まれます。

  • プロジェクトの Amazon Cognito ユーザープールから一意のプレイヤー ID を取得します (これはデプロイされた Anywhere ソリューションの一部です)。

スタートアップゲームマップを使用するには
  1. UE エディタで、[プロジェクト設定、マップ & モード] ページを開き、[デフォルトマップ] セクションを展開します。

  2. Editor Startup Map で、ドロップダウンリストからStartupMap「」を選択します。... > Unreal Projects/[project-name]/Plugins/Amazon GameLift Plugin Content/Maps にあるファイルを検索しなければいけない場合があります。

  3. ゲームデフォルトマップ で、ドロップダウンリストから同じStartupMap「」を選択します。

  4. サーバーデフォルトマップ で、ThirdPersonMap「」を選択します。これはゲームプロジェクトに含まれるデフォルトのマップです。このマップはゲーム内の 2 人のプレイヤー向けに設計されています。

  5. サーバーのデフォルトマップの詳細パネルを開きます。GameMode オーバーライドを「なし」に設定します。

  6. [デフォルトモード] セクションを展開し、[グローバルデフォルトサーバーゲームモード] をサーバー統合用に更新したゲームモードに設定します。

プロジェクトにこれらの変更を加えたら、ゲームコンポーネントを構築する準備が整います。

ゲームコンポーネントを構築する

  1. 新しいサーバーとクライアントのターゲットファイルを作成する

    1. ゲームプロジェクトフォルダで、ソースフォルダに移動し、Target.cs ファイルを見つけます。

    2. [project-name]Editor.Target.cs ファイルを、[project-name]Client.Target.cs および [project-name]Server.Target.cs という名前の 2 つの新しいファイルにコピーします。

    3. 次に示すように、新しいファイルをそれぞれ編集して、クラス名とターゲットタイプの値を更新します。

    UnrealProjects > MyGame > Source > MyGameClient.Target.cs // Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; using System.Collections.Generic; public class MyGameClientTarget : TargetRules { public MyGameClientTarget(TargetInfo Target) : base(Target) { Type = TargetType.Client; DefaultBuildSettings = BuildSettingsVersion.V2; IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_1; ExtraModuleNames.Add("MyGame"); } }
    UnrealProjects > MyGame > Source > MyGameServer.Target.cs // Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; using System.Collections.Generic; public class MyGameServerTarget : TargetRules { public MyGameServerTarget(TargetInfo Target) : base(Target) { Type = TargetType.Server; DefaultBuildSettings = BuildSettingsVersion.V2; IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_1; ExtraModuleNames.Add("MyGame"); } }
  2. .Build.cs ファイルを更新します。

    1. プロジェクトの .Build.cs ファイルを開きます。このファイルは UnrealProjects/[project name]/Source/[project name]/[project name].Build.cs にあります。

    2. 次のコードサンプルに示すように、ModuleRules クラスを更新します。

      public class MyGame : ModuleRules { public GameLiftUnrealApp(TargetInfo Target) { PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" }); bEnableExceptions = true; if (Target.Type == TargetRules.TargetType.Server) { PublicDependencyModuleNames.AddRange(new string[] { "GameLiftServerSDK" }); PublicDefinitions.Add("WITH_GAMELIFT=1"); } else { PublicDefinitions.Add("WITH_GAMELIFT=0"); } } }
  3. ゲームプロジェクトソリューションを再構築します。

  4. Unreal Engine エディタのソースビルドバージョンでゲームプロジェクトを開きます。

  5. クライアントとサーバーの両方で以下の操作を実行します。

    1. ターゲットを選択します。[プラットフォーム、Windows] に移動し、次のいずれかを選択します。

      • サーバー: [your-application-name]Server

      • クライアント: [your-application-name]Client

    2. ビルドを開始します [プラットフォーム、Windows、パッケージプロジェクト] に移動します。

パッケージ化処理を行うたびに、[your-application-name]Client.exe または [your-application-name]Server.exe という実行ファイルが生成されます。

プラグインで、ローカルワークステーションにクライアントとサーバーのビルド実行ファイルへのパスを設定します。

ステップ 3: Anywhere フリートに接続する

このステップでは、使用する Anywhere フリートを指定します。Anywhere フリートは、ゲームサーバーをホスティングするための、どこにでも配置できる一連のコンピューティングリソースを定義します。

  • 現在使用している AWS アカウントに既存の Anywhere フリートがある場合は、フリート名ドロップダウンフィールドを開き、フリートを選択します。このドロップダウンには、現在アクティブなユーザープロファイルの AWS リージョン内の Anywhere フリートのみが表示されます。

  • 既存のフリートがない場合、または新しいフリートを作成する場合は、[新しい Anywhere フリートを作成する] を選択してフリート名を指定します。

プロジェクトに Anywhere フリートを選択すると、Amazon はフリートステータスがアクティブであることを GameLift 検証し、広告にフリート ID が表示されます。このリクエストの進行状況は、Unreal エディタの出力ログで追跡できます。

ステップ 4: ワークステーションを登録する

このステップでは、ローカルワークステーションを新しい Anywhere フリートのコンピューティングリソースとして登録します。

  1. ローカルマシンのコンピューティング名を入力します。フリートに複数のコンピューティングを追加する場合、名前は一意でなければなりません。

  2. ローカルマシンの IP アドレスを入力します。このフィールドのデフォルトは、マシンのパブリック IP アドレスです。ゲームクライアントとサーバーを同じマシンで実行している限り、localhost (127.0.0.1) を使用することもできます。

  3. [コンピューティングを登録] を選択します。このリクエストの進行状況は、Unreal エディタの出力ログで追跡できます。

このアクションに応答して、Amazon はコンピューティングに接続できる GameLift ことを確認し、新しく登録されたコンピューティングに関する情報を返します。また、Amazon GameLift サービスとの通信を初期化する際にゲーム実行可能ファイルに必要なコンソール引数も作成します。

ステップ 5: 認証トークンを生成する

Anywhere コンピューティングで実行されているゲームサーバープロセスには、 GameLift サービスを呼び出すための認証トークンが必要です。プラグインからゲームサーバーを起動するたびに、プラグインは Anywhere フリートの認証トークンを自動的に生成して保存します。認証トークンの値はコマンドライン引数として保存され、サーバーコードはランタイム時にそれを取得できます。

このステップでは何もする必要はありません。

ステップ 6: ゲームを起動する

この時点で、Amazon を使用してローカルワークステーションでマルチプレイヤーゲームを起動してプレイするために必要なすべてのタスクが完了しました GameLift。

  1. ゲームサーバーを起動します。ゲームサーバーは、ゲームセッションをホストする準備ができ GameLift たら Amazon に通知します。

  2. ゲームクライアントを起動し、新しい機能を使用して新しいゲームセッションを開始します。このリクエストは、新しいバックエンドサービス GameLift を介して Amazon に送信されます。それに応じて、Amazon はローカルマシンで実行されているゲームサーバーを GameLift呼び出して、新しいゲームセッションを開始します。ゲームセッションがプレイヤーを受け入れる準備ができたら、Amazon はゲームクライアントがゲームセッションに参加するための接続情報 GameLift を提供します。