2019년 12월 4일 수요일

ue4 - 데디케이티드 서버(dedicated server tutorial)

  • 신고

  • 0. 프로젝트 소스가 없거나 다른 엔진 버전으로 작성되었거나 단순히 Blueprint 만으로 시작한 경우 일부 C++ 코드를 추가할 때까지 전용서버를 만들 수 없음


    0-1. 소스 디렉토리가 있으면 .uproject 파일을 마우스 우클릭 후 프로젝트 파일 생성


    0-2. 해당 포스팅은 4.14~17까지를 범위로 보며, 필자는 4.16.3 버전을 기준으로 작성


    1. Unreal Engine GitHub(https://github.com/EpicGames/UnrealEngine)에서 원하는 버전의 엔진 다운로드


    2. 엔진 폴더에서 [Setup.bat] 실행


    3. 이상 없이 종료될 경우 [GenerateProjectFiles.bat] 실행


    3-1. 만약 Visual Studio 2017을 사용할 경우 CMD 프롬프트 창을 이용해 해당 경로로 이동 후 [GenerateProjectFiles.bat -2017] 명령 실행


    4. 이상 없이 종료될 경우 [UE4.sln] 실행


    5. 상단 메뉴의 드랍 박스에서 솔루션 구성을 [Development Editor]로 선택


    6. UE4 솔루션을 시작 솔루션으로 설정하고 실행하여 빌드


    7. 빌드가 정상적으로 완료되어 에디터 창이 생성될 경우 셰이더 컴파일링이 끝날 때까지 대기


    8. [New Project] > [C++] > [Third Person] > [With Starter Content] > [Create Project]


    9. 생성과 로드가 완전히 끝나면 프로젝트 종료


    10. [(ProjectPath)/Source/] 경로에서 [(ProjectName)Editor.Target.cs] 파일을 같은 경로에 복사 후 [(ProjectName)Server.Target.cs]로 이름 변경


    10-1. 괄호 안의 내용은 프로젝트를 만들 때 기입되는 내용이기 때문에 상대적이며, 이후 내용들도 마찬가지


    11. [(ProjectName)Server.Target.cs] 편집


    12. 내용을 전부 지우고 엔진 버전에 따라 다음과 같이 입력


    12-1. 아래 내용은 4.14 버전에 해당
    ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
    using UnrealBuildTool;
    using System.Collections.Generic;
    public class (ProjectName)ServerTarget : TargetRules
    {
        public (ProjectName)ServerTarget(TargetInfo Target)
        {
            Type = TargetType.Server;
            bUsesSteam = true;
        }
        //
        // TargetRules interface.
        //
        public override bool GetSupportedPlatforms(ref List<UnrealTargetPlatform> OutPlatforms)
        {
            // It is valid for only server platforms
            return UnrealBuildTool.UnrealBuildTool.GetAllServerPlatforms(ref OutPlatforms, false);
        }
        public override void SetupBinaries
        (
             TargetInfo Target, ref List<UEBuildBinaryConfiguration> OutBuildBinaryConfigurations,
             ref List<string> OutExtraModuleNames
        )
        {
            OutExtraModuleNames.Add("Test");
        }
    }
    cs
    ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


    12-2. 아래 내용은 4.15 버전에 해당
    ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
    using UnrealBuildTool;
    using System.Collections.Generic;
    [SupportedPlatforms(UnrealPlatformClass.Server)]
    public class (ProjectName)ServerTarget : TargetRules      // Change this line of code as shown in the previous steps
    {
        public (ProjectName)ServerTarget(TargetInfo Target)  // Change this line of code as shown in the previous steps
        {
            Type = TargetType.Server;
            bUsesSteam = false;
        }
        //
        // TargetRules interface.
        //
        public override void SetupBinaries
        (
            TargetInfo Target,
            ref List<UEBuildBinaryConfiguration> OutBuildBinaryConfigurations,
            ref List<string> OutExtraModuleNames
        )
        {
            OutExtraModuleNames.Add("Test");     // Change this line of code as shown in the previous steps
        }
    }
    cs
    ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


    12-3. 아래 내용은 4.16 버전에 해당
    ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
    using UnrealBuildTool;
    using System.Collections.Generic;
    [SupportedPlatforms(UnrealPlatformClass.Server)]
    public class (ProjectName)ServerTarget : TargetRules    // Change this line of code as shown previously
    {
        public (ProjectName)ServerTarget(TargetInfo Target) : base(Target) // Change this line of code as shown previously
        {
            Type = TargetType.Server;
            ExtraModuleNames.Add("Test");   // Change this line of code as shown previously
        }
    }
    cs
    ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


    12-4. 아래 내용은 4.17 버전에 해당
    ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
    using UnrealBuildTool;
    using System.Collections.Generic;
    [SupportedPlatforms(UnrealPlatformClass.Server)]
    public class (ProjectName)ServerTarget : TargetRules   // Change this line as shown previously
    {
        public (ProjectName)ServerTarget(TargetInfo Target) : base(Target)  // Change this line as shown previously
        {
            Type = TargetType.Server;
            ExtraModuleNames.Add("Test");    // Change this line as shown previously
        }
    }
    cs

    ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


    13. [(ProjectPath)/] 경로에서 [(ProjectName).uproject]를 마우스 우클릭 후 [Switch Unreal Engine version] 선택


    14. 드롭 박스에서 소스 빌드 버전을 선택하고 [OK] 버튼 클릭


    14-1. 만약 이미 소스 빌드 버전이 선택되어 있다면 다른 엔진 버전으로 switch 한 뒤 다시 소스 빌드 버전으로 switch


    14-2. 이것을 하지 않을 경우 솔루션 구성을 Development Server로 하더라도 서버 바이너리 파일이 생성되지 않음 (이유 불명확)


    15. [(ProjectPath)/] 경로에서 [(ProjectName).sln] 실행


    16. 상단 메뉴의 드롭 박스에서 [Development Editor] 선택 후 (ProjectName) 솔루션을 선택하여 빌드


    17. 빌드가 정상적으로 종료될 경우 상단 메뉴의 드롭 박스에서 [Development Server] 선택 후 (ProjectName) 솔루션을 선택하여 빌드


    18. 빌드가 정상적으로 종료될 경우 [(ProjectPath)/] 경로로 돌아가 [binaries/win64/] 경로에 제대로 [(ProjectName)Server] 라는 이름의 서버 바이너리가 존재하는지 확인


    18-1. 서버 바이너리가 없다면 위의 내용을 다시 살펴보고 넘어간 부분이 있는지 체크


    19. 만약 광원을 구축할 때 소스가 비현실적으로 구축되면 [Lighting build failed. Swarm failed to kick off.]라는 오류가 출력되는데, 이 경우 프로젝트 솔루션을 열고 [UnrealLightmass] 솔루션을 선택하여 빌드하는 것으로 해결


    20. [(ProjectPath)/] 경로에서 [(ProjectName).uproject] 실행


    21. 다음과 같은 폴더 3개를 루트 경로에 생성


    21-1. [Blueprints], [Blueprints/Widgets], [Maps]


    22. [Game/ThirdPersonCPP/Maps] 안에 있는 [ThirdPersonExampleMap], [ThirdPersonExampleMap_BuiltData]를 선택하여 [Game/Maps]로 이동 후 [TestLevel]로 이름 변경


    23. 상단 메뉴의 [파일] > [새 레벨] > [공백 레벨] > [EntryMap], [TransitionMap]라는 이름의 2개의 공백 레벨 생성


    24. [EntryMap]을 열고 에디터 상단 메뉴의 [Blueprints] 선택 후 드랍 박스에서 [Open Level Blueprint] 선택


    25. [Open Level] 노드를 생성해 Level Name을 [127.0.0.1]로 설정하고 [Event BeginePlay] 노드와 연결한 뒤 컴파일 후 저장


    26. [Game/Blueprints/Widgets/] 경로에서 Content Browser에서 마우스 우클릭 후 [User Interface] > [Widget Blueprint]를 선택하여 생성


    27. Text를 하나 Widget에 배치하고 컴파일 후 저장


    28. [TransitionMap]을 열고 에디터 상단 메뉴의 [Blueprints] 선택 후 드랍 박스에서 [Open Level Blueprint] 선택


    29. [Create Widget] 노드를 생성 후 26번에서 생성한 Widget Blueprint를 선택한 뒤 [Event BeginePlay] 노드와 연결


    30. [Create Widget]의 Owning Player를 [Get Player Controller] 노드와 연결 (플레이어 인덱스 : 0)


    31. [Add to Viewport] 노드를 생성하여 [Create Widget] 노드와 연결 후 Target을 [Create Widget] 노드의 Return Value와 연결


    32. [TextLevel]을 열고 플레이어 캐릭터 삭제 후 저장


    33. 에디터로 돌아가 상단 메뉴의 [편집] > [맵 & 모드] 선택


    34. [Default Maps] 탭에서 [Editor Startup Map]을 [EntryMap]으로, [Game Default Map]을 [EntryMap]으로, [Transition Map]을 [TransitionMap]으로, [Server Default Map]을 [TestLevel]로 설정


    35. 에디터로 돌아가 상단 메뉴의 [파일] > [패키지 프로젝트] > [패키징 세팅] 선택


    36. [Packaging] 탭에서 [고급 표시]를 선택하여 탭을 확장하고, [List of maps to include in a packaged build]에 + 버튼을 3번 눌러 3개의 앨리먼트를 추가한 뒤 [0]에는 [/Game/Maps/EntryMap], [1]에는 [/Game/Maps/TestLevel], [2]에는 [/Game/Maps/TransitionMap]을 선택


    37. 에디터로 돌아가 상단 메뉴의 [파일] > [패키지 프로젝트] > [윈도우] > [윈도우(64-bit)] 선택


    38. [(ProjectPath)/Binaries/Win64/] 경로에서 [(ProjectName)Server.exe]을 복사하고 [WindowsNoEditor/(ProjectName)/Binaries/Win64/] 경로에 붙여넣기


    39. 복사한 파일의 바로가기를 생성하여 이름을 [(ProjectName)Server.exe - TestLevel]로 변경 후 마우스 우클릭하여 [속성] 선택


    40. [대상] 탭 내용의 마지막에 [ -log] 추가 후 확인을 선택하고 바로가기 실행


    41. [(ProjectName).exe]를 여러 번 실행하여 제대로 실행할 때마다 타 플레이어가 참가되는지 확인


    -> 친구가 게임에 인터넷을 통해 참여할 수 있도록 허용하려면 [EntryMap]의 레벨 블루프린트에서 로컬 IP 주소 대신 실제 공개 IP 주소를 입력


    - 만약 친구가 게임에 인터넷을 통해 참여할 수 없다면 포트가 전달되지 않고 라우터에서 제대로 설정되지 않아 고정 IP 주소를 설정해야 할 수 있음


    -> 4.4.3에서 시뮬레이트 된 물리에 따라 동작이 달라지는 액터를 복제하는 경우 SkeletalMeshComponent.bEnablePhysicsOnDedicatedServer 속성을 true로 설정


    - 독립 실행형 전용 서버는 IsRunningDedicatedServer()에 true를 반환하기 때문에 명시적으로 bEnablePhysicsOnDedicatedServer 속성을 설정하지 않은 SkeletalMeshComponents에 대한 물리 시뮬레이션을 방지 가능



    출처 : https://m.blog.naver.com/ratoa/221096604157