View a markdown version of this page

Plugin per Unreal: integra il tuo codice di gioco - GameLift Server Amazon

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Plugin per Unreal: integra il tuo codice di gioco

Prima di poter distribuire il tuo server di gioco su una flotta, devi apportare una serie di aggiornamenti al codice del gioco e impacchettare i componenti del gioco da utilizzare con il Amazon GameLift Servers servizio.

Questo argomento illustra i passaggi necessari per eseguire un'integrazione minima. Per l'integrazione con il server, usa l'esempio di codice fornito per aggiornare la modalità di gioco del tuo progetto.

Imposta gli obiettivi di compilazione e le regole dei moduli

Modifica i file di progetto del gioco per generare correttamente i componenti di build da utilizzareAmazon GameLift Servers.

Per aggiungere obiettivi di compilazione per client e server:
  1. Apri i file di codice del tuo progetto di gioco e individua il .../Games/[your application name]Source/[your application name]Target.cs file. Esempio: .../Source/GameLiftUnrealAppTarget.cs. (Se usi Visual Studio, apri il .sln file del progetto.)

  2. Copia questo file per creare due nuovi file di destinazione nella Source/ directory.

    • Destinazione del client: rinomina il nuovo file in[your application name]Client.Target.cs. Modifica i contenuti per aggiornare il nome della classe e i valori del tipo di destinazione, come illustrato nel seguente codice di esempio:

      using 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"); } }
    • Destinazione del server: rinomina il nuovo file in. [your application name]Server.Target.cs Modificate i contenuti per aggiornare il nome della classe e i valori del tipo di destinazione, come illustrato nel seguente codice di esempio:

      using 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"); } }
  3. Rigenera i tuoi file di progetto. Se usi Visual Studio, puoi fare clic con il pulsante destro del mouse sul .uproject file del progetto di gioco e selezionare Genera file di progetto di Visual Studio.

Per aggiornare le regole del modulo del progetto di gioco:

Aggiorna le regole del modulo del progetto di gioco in modo che diventi dipendente dal plugin.

  1. Apri i file di codice del tuo progetto di gioco e individua il .../Games/[your application name]Source/[your application name].Build.cs file. Esempio: .../Source/GameLiftUnrealApp.Build.cs. (Se usi Visual Studio, apri il .sln file del progetto.)

  2. Individua la ModuleRules classe e aggiorna come illustrato nel seguente codice di esempio:

    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; } }
  3. Dopo aver creato i nuovi file di destinazione e modificato le regole del modulo, ricostruisci il tuo progetto di gioco.

Aggiorna il codice del server di gioco

Aggiorna il codice del server di gioco per consentire la comunicazione tra un processo del server di gioco e il Amazon GameLift Servers servizio. Il server di gioco deve essere in grado di rispondere alle richieste provenientiAmazon GameLift Servers, ad esempio, dall'avvio e dall'interruzione di nuove sessioni di gioco.

Per aggiungere il codice del server per GameLift Server Amazon
  1. Nel tuo editor di codice, apri il file solution (.sln) per il tuo progetto di gioco, che di solito si trova nella cartella principale del progetto. Ad esempio: GameLiftUnrealApp.sln.

  2. Con la soluzione aperta, individua il file di intestazione della modalità di gioco del progetto: [project-name]GameMode.h file. Ad esempio: GameLiftUnrealAppGameMode.h.

  3. Cambia il file di intestazione in modo che sia allineato al codice seguente. Assicurati di sostituire "GameLiftServer" con il nome del tuo progetto. Questi aggiornamenti sono specifici per il server di gioco; ti consigliamo di creare una copia di backup dei file originali della modalità di gioco da utilizzare con il tuo client.

// 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; };
  • Apri il [project-name]GameMode.cpp file sorgente correlato (ad esempioGameLiftUnrealAppGameMode.cpp). Modificate il codice per allinearlo al seguente codice di esempio. Assicurati di sostituire "GameLiftUnrealApp" con il nome del tuo progetto. Questi aggiornamenti sono specifici per il server di gioco; ti consigliamo di creare una copia di backup del file originale da utilizzare con il tuo client.

    Il codice di esempio seguente mostra come aggiungere gli elementi minimi richiesti per l'integrazione del server conAmazon GameLift Servers:

    • Inizializza un client Amazon GameLift Servers API. La InitSDK() chiamata con i parametri del server è necessaria per una flotta Amazon GameLift Servers Anywhere. Quando ci si connette a una flotta Anywhere, il plug-in memorizza i parametri del server come argomenti della console. Il codice di esempio può accedere ai valori in fase di esecuzione.

    • Implementa le funzioni di callback richieste per rispondere alle richieste del Amazon GameLift Servers servizio, tra cui OnStartGameSessionOnProcessTerminate, eonHealthCheck.

    • Chiama ProcessReady() con una porta designata per avvisare il Amazon GameLift Servers servizio quando è pronto per ospitare sessioni di gioco.

// 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 }

Integra la mappa di gioco del tuo cliente

La mappa di gioco iniziale contiene elementi di logica e interfaccia utente che includono già un codice di base per richiedere sessioni di gioco e utilizzare le informazioni di connessione per connettersi a una sessione di gioco. Puoi utilizzare la mappa così com'è o modificarla secondo necessità. Usa la mappa di gioco iniziale con altre risorse di gioco, come il progetto modello Third Person fornito da Unreal Engine. Queste risorse sono disponibili in Content Browser. Puoi usarle per testare i flussi di lavoro di distribuzione del plug-in o come guida per creare un servizio di backend personalizzato per il tuo gioco.

La mappa di avvio ha le seguenti caratteristiche:

  • Include la logica sia per una flotta Anywhere che per una flotta EC2 gestita. Quando gestisci il tuo cliente, puoi scegliere di connetterti a entrambe le flotte.

  • Le funzionalità del client includono trovare una sessione di gioco (SearchGameSessions()), creare una nuova sessione di gioco (CreateGameSession()) e partecipare direttamente a una sessione di gioco.

  • Riceve un ID giocatore univoco dal pool di utenti Amazon Cognito del tuo progetto (fa parte di una soluzione distribuita Anywhere).

Per utilizzare la mappa di avvio del gioco
  1. Nell'editor UE, apri la pagina Impostazioni del progetto, Mappe e modalità ed espandi la sezione Mappe predefinite.

  2. Per Editor Startup Map, seleziona StartupMap "" dall'elenco a discesa. Potrebbe essere necessario cercare il file, che si trova in... > Unreal Projects/[project-name]/Plugins/Amazon GameLift Servers Plugin Content/Maps.

    Nota

    Per trovare la mappa di avvio di esempio, seleziona l'icona delle impostazioni e scegli Mostra contenuto del plug-in.

  3. Per Game Default Map, seleziona lo stesso StartupMap "" dall'elenco a discesa.

  4. Per Server Default Map, seleziona «Lv1_ThirdPerson" per Unreal Engine 5.6 o versioni successive o "" ThirdPersonMap per le versioni precedenti. Questa è una mappa predefinita inclusa nel tuo progetto di gioco. Questa mappa è progettata per due giocatori nel gioco.

  5. Apri il pannello dei dettagli per la mappa predefinita del server. Imposta GameMode Override su «Nessuno».

  6. Espandi la sezione Modalità predefinite e imposta la modalità di gioco del server predefinita globale sulla modalità di gioco che hai aggiornato per l'integrazione con il server.

Dopo aver apportato queste modifiche al progetto, sei pronto per creare i componenti di gioco.

Nota

Per Unreal Engine 5.6 o versioni successive, se non riesci a spostare il personaggio dopo esserti connesso al server di gioco, aggiorna il ThirdPersonCharacter progetto BP_ per aggiungere il contesto di mappatura degli input per e come mostrato di seguito: IMC_Default IMC_MouseLook

Nodi blueprint che mostrano i nodi Event BeginPlay connesso a Cast To PlayerController e Add Mapping Context per IMC_default e IMC_. MouseLook

Impacchetta i componenti del gioco

Per impacchettare le build del server di gioco e del client di gioco
  1. Apri il tuo progetto di gioco in una versione originale dell'editor Unreal Engine.

  2. Se usi Unreal Engine 5.6 o versioni successive, vai su Modifica, Impostazioni del progetto, Pacchettizzazione. Trova tutto Cook nella directory dei contenuti del progetto e abilitalo.

  3. Usa l'editor per impacchettare le build del client di gioco e del server.

    1. Scegli un bersaglio. Vai su Piattaforme, Windows e seleziona una delle seguenti opzioni:

      • Server: [your-application-name]Server

      • Client: [your-application-name]Client

    2. Inizia la compilazione. Vai a Platform, Windows, Package Project.

Ogni processo di creazione di pacchetti genera un file eseguibile: [your-application-name]Client.exe o[your-application-name]Server.exe.

Nel plugin, imposta i percorsi degli eseguibili di build del client e del server sulla tua workstation locale.