

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Unreal용 플러그인: 게임 코드 통합
<a name="unreal-plugin-integrate"></a>

게임 서버를 플릿에 배포하려면 먼저 Amazon GameLift Servers 서비스와 함께 사용할 게임 코드 및 패키지 게임 구성 요소에 대한 일련의 업데이트를 수행해야 합니다.

이 주제에서는 최소한의 통합을 수행하는 단계를 안내합니다. 서버 통합의 경우 제공된 코드 샘플을 사용하여 프로젝트의 게임 모드를 업데이트합니다.
+ [빌드 대상 및 모듈 규칙 설정](#unreal-plugin-anywhere-integrate-setup)
+ [게임 서버 코드 업데이트](#unreal-plugin-anywhere-integrate-simple-server)
+ [클라이언트 게임 맵 통합](#unreal-plugin-anywhere-integrate-simple-client)
+ [게임 구성 요소 패키징](#unreal-plugin-anywhere-integrate-build)

## 빌드 대상 및 모듈 규칙 설정
<a name="unreal-plugin-anywhere-integrate-setup"></a>

게임 프로젝트 파일을 수정하여 Amazon GameLift Servers에 사용할 빌드 구성 요소를 올바르게 생성합니다.

**클라이언트 및 서버 빌드 대상을 추가하려면:**

1. 게임 프로젝트의 코드 파일을 열고 `.../Games/{{[your application name]}}Source/{{[your application name]}}Target.cs` 파일을 찾습니다. 예시: `.../Source/GameLiftUnrealAppTarget.cs`. (Visual Studio를 사용하는 경우 프로젝트의 `.sln` 파일을 엽니다.)

1. 이 파일을 복사하여 `Source/` 디렉터리에 두 개의 새 대상 파일을 생성합니다.
   + 클라이언트 대상 - 새 파일의 이름을 `{{[your application name]}}Client.Target.cs`로 변경합니다. 다음 샘플 코드에 설명한 대로 콘텐츠를 편집하여 클래스 이름과 대상 유형 값을 업데이트합니다.

     ```
     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");
          }
      }
     ```
   + 서버 대상 - 새 파일의 이름을 `{{[your application name]}}Server.Target.cs`로 변경합니다. 다음 샘플 코드에 설명한 대로 콘텐츠를 편집하여 클래스 이름과 대상 유형 값을 업데이트합니다.

     ```
     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");
          }
      }
     ```

1. 프로젝트 파일을 다시 생성합니다. Visual Studio를 사용하는 경우 게임 프로젝트의 `.uproject` 파일을 마우스 오른쪽 버튼으로 클릭하고 **Visual Studio 프로젝트 파일 생성**을 선택할 수 있습니다.

**게임 프로젝트 모듈 규칙을 업데이트하려면:**

플러그인에 종속되도록 게임 프로젝트의 모듈 규칙을 업데이트합니다.

1. 게임 프로젝트의 코드 파일을 열고 `.../Games/{{[your application name]}}Source/{{[your application name]}}.Build.cs` 파일을 찾습니다. 예시: `.../Source/GameLiftUnrealApp.Build.cs`. (Visual Studio를 사용하는 경우 프로젝트의 `.sln` 파일을 엽니다.)

1. `ModuleRules` 클래스를 찾고 다음 샘플 코드에 표시된 대로 업데이트합니다.

   ```
   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;
        }
    }
   ```

1. 새 대상 파일을 생성하고 모듈 규칙을 수정한 후 게임 프로젝트를 다시 빌드합니다.

## 게임 서버 코드 업데이트
<a name="unreal-plugin-anywhere-integrate-simple-server"></a>

게임 서버 코드를 업데이트하여 게임 서버 프로세스와 Amazon GameLift Servers 서비스 간에 통신할 수 있습니다. 게임 서버는 새 게임 세션을 시작하고 중지하는 등 Amazon GameLift Servers의 요청에 응답할 수 있어야 합니다.

**Amazon GameLift Servers에 대한 서버 코드를 추가하려면**

1. 코드 편집기에서 일반적으로 프로젝트 루트 폴더에 있는 게임 프로젝트의 솔루션(`.sln`) 파일을 엽니다. 예를 들어 `GameLiftUnrealApp.sln`입니다.

1. 솔루션이 열린 상태에서 프로젝트 게임 모드 헤더 파일인 `[project-name]GameMode.h` 파일을 찾습니다. 예를 들어 `GameLiftUnrealAppGameMode.h`입니다.

1. 헤더 파일을 다음 코드에 맞게 변경합니다. 반드시 ‘GameLiftServer’을 사용자 고유의 프로젝트 이름으로 변경해야 합니다. 이러한 업데이트는 게임 서버에만 적용되므로 클라이언트에서 사용할 수 있도록 원본 게임 모드 파일의 백업 복사본을 만드는 것이 좋습니다.

### gameMode.h 코드 예제
<a name="w2aab9c11b9c19c27c11b7b1"></a>

```
// 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;
};
```
+ 관련 소스 파일인 `[project-name]GameMode.cpp` 파일(예: `GameLiftUnrealAppGameMode.cpp`)을 엽니다. 코드를 다음 예제 코드에 맞게 변경합니다. 반드시 “GameLiftUnrealApp”을 사용자 고유의 프로젝트 이름으로 변경해야 합니다. 이러한 업데이트는 게임 서버에만 적용되므로 클라이언트에서 사용할 수 있도록 원본 파일의 백업 복사본을 만드는 것이 좋습니다.

  다음 예제 코드는 Amazon GameLift Servers와 서버 통합에 필요한 최소 요소를 추가하는 방법을 보여 줍니다.
  + Amazon GameLift Servers API 클라이언트를 초기화합니다. Amazon GameLift Servers Anywhere 플릿에는 서버 파라미터를 사용한 `InitSDK()` 호출이 필요합니다. Anywhere 플릿에 연결하면 플러그인은 서버 파라미터를 콘솔 인수로 저장합니다. 샘플 코드는 런타임 시 값에 액세스할 수 있습니다.
  + `OnStartGameSession`, `OnProcessTerminate`, `onHealthCheck`를 포함한 Amazon GameLift Servers 서비스의 요청에 응답하는 필수 콜백 함수를 구현합니다.
  + 지정된 포트와 함께 `ProcessReady()`를 호출하여 게임 세션을 호스팅할 준비가 되면 Amazon GameLift Servers 서비스에 알립니다.

### 게임 서버 코드 예제
<a name="w2aab9c11b9c19c27c11c11b1"></a>

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

## 클라이언트 게임 맵 통합
<a name="unreal-plugin-anywhere-integrate-simple-client"></a>

스타트업 게임 맵에는 게임 세션을 요청하고 연결 정보를 사용하여 게임 세션에 연결하는 기본 코드가 이미 포함되어 있는 블루프린트 로직과 UI 요소가 포함되어 있습니다. 맵을 그대로 사용하거나 필요에 따라 수정할 수 있습니다. 스타트업 게임 맵을 다른 게임 애셋(예: Unreal Engine에서 제공하는 3인칭 템플릿 프로젝트)과 함께 사용합니다. 이러한 애셋은 콘텐츠 브라우저에서 사용할 수 있습니다. 이를 사용하여 플러그인의 배포 워크플로를 테스트하거나 게임에 맞는 사용자 지정 백엔드 서비스를 만들기 위한 가이드로 사용할 수 있습니다.

스타트업 맵에는 다음과 같은 특성이 있습니다.
+ 여기에는 Anywhere 플릿과 관리형 EC2 플릿 모두에 대한 로직이 포함됩니다. 클라이언트를 실행할 때 두 플릿 중 하나에 연결하도록 선택할 수 있습니다.
+ 클라이언트 기능에는 게임 세션 찾기(`SearchGameSessions()`), 새 게임 세션 생성(`CreateGameSession()`), 게임 세션에 직접 참여 등이 포함됩니다.
+ 프로젝트의 Amazon Cognito 사용자 풀(배포된 Anywhere 솔루션의 일부)에서 고유한 플레이어 ID를 가져옵니다.

**스타트업 게임 맵을 사용하려면**

1. UE 편집기에서 **프로젝트 설정, 맵 및 모드** 페이지를 열고 **기본 맵** 섹션을 확장합니다.

1. **편집기 스타트업 맵**의 경우 드롭다운 목록에서 ‘StartupMap’을 선택합니다. `... > Unreal Projects/[project-name]/Plugins/Amazon GameLift Servers Plugin Content/Maps`에 있는 파일을 검색해야 할 수도 있습니다.

1. **게임 기본 맵**의 경우 드롭다운 목록에서 동일한 ‘StartupMap’을 선택합니다.

1. **서버 기본 맵**에서 Unreal Engine 5.6 이상의 경우 "Lv1\_ThirdPerson"을 선택하고 이전 버전의 경우 "ThirdPersonMap"을 선택합니다. 이는 게임 프로젝트에 포함된 기본 맵입니다. 이 맵은 게임에 참여하는 두 명의 플레이어를 위해 설계되었습니다.

1. 서버 기본 맵의 세부 정보 패널을 엽니다. **GameMode 재정의**를 ‘없음’으로 설정합니다.

1. **기본 모드** 섹션을 확장하고 **전역 기본 서버 게임 모드**를 서버 통합을 위해 업데이트한 게임 모드로 설정합니다.

프로젝트를 이렇게 변경했으면 게임 구성 요소를 빌드할 준비가 된 것입니다.

**참고**  
Unreal Engine 5.6 이상의 경우 게임 서버에 연결한 후 캐릭터를 이동할 수 없는 경우 아래와 `IMC_MouseLook` 같이 BP\_ThirdPersonCharacter 블루프린트를 업데이트하여 `IMC_Default` 및에 대한 입력 매핑 컨텍스트를 추가합니다.  

![](http://docs.aws.amazon.com/ko_kr/gameliftservers/latest/developerguide/images/unreal-enhanced-input-blueprint.png)


## 게임 구성 요소 패키징
<a name="unreal-plugin-anywhere-integrate-build"></a>

**게임 서버 및 게임 클라이언트 빌드를 패키징하려면**

1. Unreal Engine 편집기의 소스 빌드 버전에서 게임 프로젝트를 엽니다.

1. Unreal Engine 5.6 이상을 사용하는 경우 **편집, 프로젝트 설정, 패키징**으로 이동합니다. **프로젝트 콘텐츠 디렉터리에서 모든 Cook을** 찾아 활성화합니다.

1. 편집기를 사용하여 게임 클라이언트 및 서버 빌드를 패키징합니다.

   1. 대상을 선택합니다. **플랫폼, Windows**로 이동하여 다음 중 하나를 선택합니다.
      + 서버: `[your-application-name]Server`
      + 클라이언트: `[your-application-name]Client`

   1. 빌드를 시작합니다. **플랫폼, Windows, 패키지 프로젝트**로 이동합니다.

각 패키징 프로세스는 실행 파일(`[your-application-name]Client.exe` 또는 `[your-application-name]Server.exe`)을 생성합니다.

플러그인에서 로컬 워크스테이션에 있는 클라이언트 및 서버 빌드 실행 파일의 경로를 설정합니다.