Integre o Amazon GameLift Servers em um projeto Unreal Engine
Aprenda a integrar o Amazon GameLift Servers SDK para o Unreal Engine em seus projetos de jogos para acessar o conjunto completo de atributos do SDK do servidor.
Dica
Para uma implantação mais rápida, experimente o plug-in independente do Amazon GameLift Servers para o Unreal Engine. Ele fornece fluxos de trabalho de interface de usuário guiados para implantar rapidamente seu servidor de jogos com configuração mínima, para que você possa testar os componentes do jogo em ação. Consulte Amazon GameLift ServersPlug-in para Unreal Engine.
Recursos adicionais:
Instalar o SDK do servidor para o Unreal Engine
Obtenha o código aberto Amazon GameLift Servers SDK para o Unreal Engine no GitHub.
Configure metas de construção e regras de módulo
Modifique seus arquivos de projeto de jogo para gerar corretamente componentes de compilação para uso com o Amazon GameLift Servers.
Para adicionar destinos de criação de cliente e servidor:
-
Abra os arquivos de código do seu projeto de jogo e localize o arquivo
.../Games/. Exemplo:[your application name]Source/[your application name]Target.cs.../Source/GameLiftUnrealAppTarget.cs. (Se você usa o Visual Studio, abra o arquivo do.slndo projeto.) -
Copie esse arquivo para criar dois novos arquivos de destino no diretório
Source/.Destino do cliente – Renomeie o novo arquivo para
. Edite o conteúdo para atualizar os valores do nome da classe e do tipo de destino, conforme ilustrado no código de exemplo a seguir:[your application name]Client.Target.csusing UnrealBuildTool; using System.Collections.Generic; public class GameLiftUnrealAppClientTarget : TargetRules { public GameLiftUnrealAppClientTarget ( TargetInfo Target ) : base ( Target ) { Type = TargetType.Client; DefaultBuildSettings = BuildSettingsVersion.V2; IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_1; ExtraModuleNames.Add( "GameLiftUnrealApp"); } }-
Destino do servidor – Renomeie o novo arquivo para
. Edite o conteúdo para atualizar os valores do nome da classe e do tipo de destino, conforme ilustrado no código de exemplo a seguir:[your application name]Server.Target.csusing UnrealBuildTool; using System.Collections.Generic; public class GameLiftUnrealAppServerTarget : TargetRules { public GameLiftUnrealAppServerTarget ( TargetInfo Target ) : base ( Target ) { Type = TargetType.Server; DefaultBuildSettings = BuildSettingsVersion.V2; IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_1; ExtraModuleNames.Add( "GameLiftUnrealApp"); } }
-
Gere novamente os arquivos do projeto. Se você estiver usando o Visual Studio, você pode clicar com o botão direito do mouse no arquivo
.uprojectdo seu projeto de jogo e selecionar Gerar arquivos de projeto do Visual Studio.
Para atualizar as regras do módulo do projeto do jogo:
Atualize as regras do módulo do projeto de jogo para depender do plug-in.
-
Abra os arquivos de código do seu projeto de jogo e localize o arquivo
.../Games/. Exemplo:[your application name]Source/[your application name].Build.cs.../Source/GameLiftUnrealApp.Build.cs. (Se você usa o Visual Studio, abra o arquivo do.slndo projeto.) -
Localize a classe
ModuleRulese atualize conforme ilustrado no código de exemplo a seguir:using UnrealBuildTool; public class GameLiftUnrealApp : ModuleRules { public GameLiftUnrealApp ( ReadOnlyTargetRules Target ) : base ( Target ) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; PublicDependencyModuleNames.AddRange( new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "EnhancedInput" }); // Add the following section if (Target.Type == TargetType.Server) { PublicDependencyModuleNames.Add("GameLiftServerSDK"); } else { PublicDefinitions.Add("WITH_GAMELIFT=0"); } bEnableExceptions = true; } } Depois de criar os novos arquivos de destino e modificar as regras do módulo, reconstrua seu projeto de jogo.
Adicione a funcionalidade de hospedagem de jogos ao código do seu servidor
Após a instalação e configuração do SDK do servidor, a próxima etapa é integrar a funcionalidade de hospedagem de jogos ao código do servidor. O SDK do servidor permite que seu servidor de jogos se comunique com o serviço do Amazon GameLift Servers, receba instruções para sessões de jogo, relate status e integridade e execute outras ações.
Este tópico fornece um exemplo de código que adiciona a funcionalidade mínima necessária para hospedar seu jogo com o Amazon GameLift Servers.
Etapa 1: atualizar o arquivo de GameMode compartilhado
-
Abra os arquivos de código do seu projeto de jogo e localize o arquivo
. Exemplo:Your-application-nameGameMode.hGameLiftUnrealAppGameMode.h. Se você usa o Visual Studio, abra o arquivo do.slndo projeto. -
Altere o arquivo de cabeçalho para incluir o código de exemplo a seguir. Certifique-se de substituir "GameLiftUnrealApp" pelo nome do seu próprio aplicativo.
// 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 "GameLiftUnrealAppGameMode.generated.h" struct FProcessParameters; DECLARE_LOG_CATEGORY_EXTERN(GameServerLog, Log, All); UCLASS(minimalapi) class AGameLiftUnrealAppGameMode : public AGameModeBase { GENERATED_BODY() public: AGameLiftUnrealAppGameMode(); protected: virtual void BeginPlay() override; private: void InitGameLift(); private: TSharedPtr<FProcessParameters> ProcessParameters; };
Etapa 2: Adicione as chamadas necessárias do SDK do servidor ao código do servidor do jogo
Use o código de amostra nesta seção para integrar o código do servidor do jogo para uso com o Amazon GameLift Servers. Para obter detalhes sobre o que o código faz, consulte Inicializar o processo do servidor e SDK do servidor C++ (Unreal) para Amazon GameLift Servers 5.x – Ações.
nota
O sinalizador de pré-processador de WITH_GAMELIFT tem duas finalidades:
Restringe as chamadas de API de backend do Amazon GameLift Servers somente para compilações de servidores Unreal
Garante compatibilidade entre diferentes destinos de compilação do Unreal
-
Abra o arquivo
de origem relacionado. Em nosso exemplo:Your-application-nameGameMode.cppGameLiftUnrealAppGameMode.cpp. Altere o código para alinhá-lo com o código de exemplo a seguir. Certifique-se de substituir qualquer instância de "GameLiftUnrealApp" pelo nome do seu próprio aplicativo.
O exemplo de código fornecido mostra como adicionar os elementos necessários para integração com o Amazon GameLift Servers. Isso inclui:
-
Inicialize um cliente da API do Amazon GameLift Servers.
-
Implemente funções de retorno de chamada para responder às solicitações do serviço do Amazon GameLift Servers, inclusive
OnStartGameSession,OnProcessTerminateeonHealthCheck. -
Chame
ProcessReady()para notificar o serviço do Amazon GameLift Servers quando estiver pronto para hospedar sessões do jogo.
-
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #include "GameLiftUnrealAppGameMode.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); AGameLiftUnrealAppGameMode::AGameLiftUnrealAppGameMode() : 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 AGameLiftUnrealAppGameMode...")); } void AGameLiftUnrealAppGameMode::BeginPlay() { Super::BeginPlay(); #if WITH_GAMELIFT InitGameLift(); #endif } void AGameLiftUnrealAppGameMode::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. FString TimeString = FString::FromInt(std::time(nullptr)); FString ProcessId = "ProcessId_" + TimeString; ServerParametersForAnywhere.m_processId = TCHAR_TO_UTF8(*ProcessId); } 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); } FString glAnywhereAwsRegion = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereAwsRegion="), glAnywhereAwsRegion)) { ServerParametersForAnywhere.m_awsRegion = TCHAR_TO_UTF8(*glAnywhereAwsRegion); } FString glAnywhereAccessKey = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereAccessKey="), glAnywhereAccessKey)) { ServerParametersForAnywhere.m_accessKey = TCHAR_TO_UTF8(*glAnywhereAccessKey); } FString glAnywhereSecretKey = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereSecretKey="), glAnywhereSecretKey)) { ServerParametersForAnywhere.m_secretKey = TCHAR_TO_UTF8(*glAnywhereSecretKey); } FString glAnywhereSessionToken = ""; if (FParse::Value(FCommandLine::Get(), TEXT("glAnywhereSessionToken="), glAnywhereSessionToken)) { ServerParametersForAnywhere.m_sessionToken = TCHAR_TO_UTF8(*glAnywhereSessionToken); } UE_LOG(GameServerLog, SetColor, TEXT("%s"), COLOR_YELLOW); UE_LOG(GameServerLog, Log, TEXT(">>>> WebSocket 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, Log, TEXT(">>>> Aws Region: %s"), *ServerParametersForAnywhere.m_awsRegion); UE_LOG(GameServerLog, Log, TEXT(">>>> Access Key: %s"), *ServerParametersForAnywhere.m_accessKey); UE_LOG(GameServerLog, Log, TEXT(">>>> Secret Key: %s"), *ServerParametersForAnywhere.m_secretKey); UE_LOG(GameServerLog, Log, TEXT(">>>> Session Token: %s"), *ServerParametersForAnywhere.m_sessionToken); 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, Amazon GameLift Servers 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. Amazon GameLift Servers 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 Amazon GameLift Servers we are indeed going to shutdown. ProcessParameters->OnTerminate.BindLambda([=]() { UE_LOG(GameServerLog, Log, TEXT("Game Server Process is terminating")); // First call ProcessEnding() FGameLiftGenericOutcome processEndingOutcome = GameLiftSdkModule->ProcessEnding(); // Then call Destroy() to free the SDK from memory FGameLiftGenericOutcome destroyOutcome = GameLiftSdkModule->Destroy(); // Exit the process with success or failure if (processEndingOutcome.IsSuccess() && destroyOutcome.IsSuccess()) { UE_LOG(GameServerLog, Log, TEXT("Server process ending successfully")); } else { if (!processEndingOutcome.IsSuccess()) { const FGameLiftError& error = processEndingOutcome.GetError(); UE_LOG(GameServerLog, Error, TEXT("ProcessEnding() failed. Error: %s"), error.m_errorMessage.IsEmpty() ? TEXT("Unknown error") : *error.m_errorMessage); } if (!destroyOutcome.IsSuccess()) { const FGameLiftError& error = destroyOutcome.GetError(); UE_LOG(GameServerLog, Error, TEXT("Destroy() failed. Error: %s"), error.m_errorMessage.IsEmpty() ? TEXT("Unknown error") : *error.m_errorMessage); } } }); //This is the HealthCheck callback. //Amazon GameLift Servers 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. Amazon GameLift Servers 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 Amazon GameLift Servers where to find game session log files. //At the end of a game session, Amazon GameLift Servers uploads everything in the specified //location and stores it in the cloud for access later. TArray<FString> Logfiles; Logfiles.Add(TEXT("GameLiftUnrealApp/Saved/Logs/server.log")); ProcessParameters->logParameters = Logfiles; //The game server calls ProcessReady() to tell Amazon GameLift Servers 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 }
Etapa 3: Reconstruir o projeto do jogo
-
Crie um projeto de jogo para os dois tipos de alvo a seguir: Editor de Desenvolvimento e Servidor de Desenvolvimento.
nota
Não é necessário reconstruir a solução. Em vez disso, crie o projeto na pasta
/Games/do seu aplicativo. Caso contrário, o Visual Studio reconstrói todo o projeto do UE5, o que pode levar até uma hora.
Inclua o servidor de jogos para hospedagem.
Com o código do servidor do jogo agora integrado à funcionalidade mínima necessária do SDK do servidor, você está pronto para empacotar a versão do seu servidor de jogos usando o Unreal Editor.
Para empacotar a versão do servidor de jogos.
-
Abra o projeto do jogo no Unreal Editor.
-
Siga as etapas do Unreal Editor para empacotar seu servidor de jogos:
-
Escolha sua plataforma de destino (Windows ou Linux).
-
Selecione o destino de compilação do seu servidor (
.[your application name]Server
O processo de empacotamento gera o executável do seu servidor de jogos:
.[your application name]Server.exe -
-
Prepare a versão do seu servidor de jogos para implantação em recursos de hospedagem. A compilação deve incluir os seguintes arquivos.
-
Seu executável do servidor de jogos
-
Se você estiver usando a versão 5.5 ou anterior do Unreal Engine, inclua os seguintes arquivos para compilações do Windows. É possível encontrá-los na versão original do Unreal Engine:
-
VC_redist.x64.exe(UnrealEngine\Engine\Source\Programs\PrereqInstaller\Resources\VCRedist\) -
UEPrereqSetup_x64.exe or UE5PrereqSetup_x64.exe(UnrealEngine\Engine\Extras\Redist\en-us\)
-
-
Todas as outras dependências necessárias para servidor de jogos.
-
Bibliotecas OpenSSL, se necessário. Você pode pular essa etapa se seu servidor de jogos estiver integrado ao SDK do servidor do Amazon GameLift Servers versão 5.3 ou posterior. A versão mais recente do SDK do servidor está disponível aqui.
-
Você deve incluir a mesma versão das bibliotecas do OpenSSL que foram usadas ao empacotar o servidor do jogo no Unreal. Essas bibliotecas estão localizadas na fonte do seu mecanismo de jogo. O local varia de acordo com o ambiente de desenvolvimento:
No Windows:
-
[ENGINE_ROOT_DIR]\Engine\Extras\ThirdPartyNotUE\libimobiledevice\x64\libssl-1_1-x64.dll -
[ENGINE_ROOT_DIR]\Engine\Extras\ThirdPartyNotUE\libimobiledevice\x64\libcrypto-1_1-x64.dll
No Linux:
-
Engine/Source/Thirdparty/OpenSSL/1.1.1n/include/libssl.so.1.1 -
Engine/Source/Thirdparty/OpenSSL/1.1.1n/include/libcrypto.so.1.1
Copie as bibliotecas do OpenSSL para o pacote de compilação do jogo no mesmo diretório do arquivo executável do servidor do jogo.
Próximas etapas
Agora que você preparou uma versão de servidor de jogos com a funcionalidade mínima necessária para hospedagem com o Amazon GameLift Servers, considere estas possíveis próximas etapas:
Implante seu servidor de jogos integrado para testes e desenvolvimento. Com uma frota Anywhere, é possível configurar sua máquina local como recurso de hospedagem e usá-la para testar as conexões do servidor de jogos e do cliente de jogos. Para hospedagem baseada em nuvem, implante seu servidor de jogos em um EC2 gerenciado ou em uma frota de contêineres gerenciada. Consulte estes tópicos para obter orientação:
Personalize a integração do servidor de jogos adicionando atributos opcionais. Por exemplo, talvez você queira adicionar sessões de jogadores com IDs de jogador exclusivos, configurar o preenchimento de criação de partidas ou gerenciar o acesso do servidor de jogos aos seus outros recursos do AWS (como um banco de dados ou serviço de armazenamento de conteúdo). Consulte estes tópicos para obter orientação:
Personalize seu componente cliente de jogo para solicitar sessões de jogo, receber informações de conexão e conectar-se diretamente a um servidor de jogos para jogar. Consulte estes tópicos para obter orientação: