이렇게 AB로 시작하는 매크로를 선언하고 컴파일을 하면 이제 UE_LOG 매크로 대신 AB_LOG 혹은 AB_LOG_CALLONLY 매크로를 동일하게 사용해주면 됩니다. 아래는 새로운 매크로로 로그 코드를 변경한 예시입니다. 반드시 헤더를 추가해야 AB_LOG를 사용 할 수가 있다.
이 매크로를 사용하면 아래 그림과 같이 로그 매크로를 사용한 시점의 함수와 라인 정보가 자동으로 함께 표시됩니다.
추가로 언리얼의 출력 로그 창에서 경고 메시지만 보이도록 필터링 하는 것도 가능합니다. 앞으로 강좌에서 함수 정보만 출력하고 싶은 경우에는 AB_LOG_CALLONLY 매크로를 추가 정보도 같이 포맷문자열로 출력하고싶은 경우에는 AB_LOG를 사용하겠습니다.
참고로 로그 매크로안에 설정할 수 있는 Verbosity 값은 총 Fatal, Error, Warning, Display등이 있습니다. Fatal을 사용하면 강제로 크래시를 일으킵니다. 하지만 로그에서 Fatal을 쓸바에야 check나 verify같은 Assertion 매크로를 사용하는게 좋습니다.
함수 목록은 TFieldIterator<UFunction>을 사용할 수 있으며, 아니면 아래 코드와 같이 NativeFunctionLookupTable 배열을 사용해 현재 클래스에 어떤 C++ 함수가 있는지 파악할 수 있습니다.
함수의 이름만 알면 FindFunctionByName 함수를 사용해 언리얼 함수 객체 UFunction을 얻어올 수 있으며 이를 사용해 특정 인스턴스 내 함수 호출이 가능합니다. 아래는 리플렉션 기능으로 함수를 호출한 예시입니다. 이번 코드에서는 C++ 11부터 지원하는 범위기반 for 루프(Range based for loop)를 사용해 간결하게 표현해보았습니다. auto문 캐스팅
아래 그림과 같이 WebConnection 객체를 생성하고 로그를 찍어봅시다. 모듈이 초기화된 후에 에디터가 로딩하므로 에디터에서 플레이 버튼을 누르지 않아도 생성자에 넣은 로그 코드가 실행된 것을 확인할 수 있습니다. 아래는 로그가 나온 결과입니다.
생성자 코드에는 단순히 멤버 변수의 기본 값을 지정하는 데에도 사용되지만, 하나의 언리얼 오브젝트가 다른 언리얼 오브젝트를 생성하고 포함하는 형태로도 많이 사용됩니다. 즉 여러 개의 언리얼 오브젝트들이 합쳐진 거대한 언리얼 오브젝트를 생성하는 형태라고 보면 됩니다.
이번에는 ArenaBattle 모듈에 있는 ABGameInstance 언리얼 오브젝트를 초기화할 때, WebService 모듈에 있는 WebConnection 언리얼 오브젝트를 생성하고 이를 보조 언리얼 오브젝트로 만들어봅시다.
이를 제작하기 위해서는 ArenaBattle 모듈이 WebService 모듈을 참조해야 합니다. 우리가 지금까지 제작한 ArenaBattle 모듈과 WebService 모듈은 하나의 프로젝트에서 만들었지만
둘은 엄연히물리적인 DLL파일로 분리된 전혀 다른 모듈이기 때문입니다.
우리는 ArenaBattle 모듈에서 WebService 모듈 내의 WebConnection 언리얼 오브젝트를 사용해야 하기 때문에 ArenaBattle.Build.cs파일의 PublicDependencyModuleNames 프로퍼티에 WebService 모듈을 추가해줍시다.
이렇게 Build.cs 파일을 설정하면언리얼 빌드 툴에 의해WebService의 Include와 Library 경로는 자동으로 ArenaBattle 모듈의 내부 빌드 설정에 추가됩니다.
이제는 아래와 같이 ArenaBattle 모듈 내 모든 폴더에서 WebService 모듈 내, Public과 Classes 폴더에 있는 헤더파일을 별도의 경로 지정 없이 바로 사용할 수 있게 되었습니다. 링크 과정도 마찬가지고요.
//ABC.Build.cs
using UnrealBuildTool;
public class ABC : ModuleRules
{
public ABC(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] {
"Core", "CoreUObject", "Engine",
"InputCore", "HeadMountedDisplay", "WebServiceK" });
}
}
이제 ABGameInstance에서 WebConnection을 선언하고 마음껏 사용해줍시다. 사용할 때 한가지 참고할 부분은 언리얼 엔진에서는 언리얼 오브젝트를 생성하고 관리할 때 특별한 일이 없는 한 거의 대부분 포인터를 사용합니다.
"WebConnection.h" 헤더파일을 인클루드한 후 언리얼 오브젝트의 포인터를 정의해줍시다. 포인터로 동작할 때 가장 큰 문제는 메모리 관리라고 할 수 있는데, 멤버 변수에 UPROPERY 매크로를 사용해주면 언리얼 엔진이 알아서 메모리를 관리해줍니다.
아래는 완성된 ABGameInstance의 헤더 파일입니다. 참고로 generated.h 헤더는 가장 마지막에 선언되어야 하는 규칙이 있다고 말씀드렸지요? 그래서 맨 마지막이 아닌 두 번째에 WebConnection.h를 추가했습니다.
참고로 클래스 선언 시에 헤더 순서를 일일히 지정하는 번거로움을 없애기 위해 class 라는 전방 선언(Forward Declaration) 키워드를 추가했습니다. 언리얼 오브젝트 선언이 다 클래스 포인터이기 때문에 가능한 일이지요~
//ABCGameInstance .h
#include "Engine/GameInstance.h"
#include "WebConnection.h"
#include "ABCGameInstance.generated.h"
UCLASS()
class ABC_API UABCGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
UABCGameInstance();
virtual void Init() override;
UPROPERTY()
class UWebConnection* WebConnection;
};
인스턴스 생성
이제 소스 파일의 생성자 코드에서는 WebConnection의 인스턴스를 생성해서 멤버 변수로 지정해주어야 합니다. A라는 언리얼 오브젝트가 초기화를 위해, B라는 언리얼 오브젝트를 생성할 때 B는 A의 서브오브젝트(Subobject)라고 합니다.
B의 외부 참조(Outer)는 A가 되고요. 따라서 생성자 코드에서 언리얼 오브젝트의 인스턴스를 생성하고, 관리하고자 한다면 언리얼 엔진이 제공하는 API인 CreateDefaultSubobject라는 API를 쓰는 것이 좋습니다. 참고로 게임 실행 코드에서는 NewObject를 사용해 언리얼 오브젝트의 인스턴스를 생성합니다.
이번 시간에는 언리얼 엔진에서 모든 오브젝트의 기본을 이루는 언리얼 오브젝트에 대해 살펴보겠습니다.
지난 강좌에서 WebService 모듈에 있는 WebConnection 객체를 생성할 때, 부모를 Object로 지정했던 것을 기억하실 겁니다.
이는 일반 오브젝트가 아닌 언리얼 오브젝트를 의미하는데, 비주얼 스튜디오에 가서 이 언리얼 오브젝트를 상속받은 WebConnection의 클래스 선언을 살펴보겠습니다.
우리는 지정하지 않았는데, WebConnection과 Object클래스 이름의 앞에 U자가 붙어 있음을 확인할 수 있습니다. 이는 클래스가 언리얼 오브젝트로 선언되었다는 것을 의미합니다.
언리얼 오브젝트는 언리얼 엔진의 관리를 받는 특수한 객체입니다. 그렇다고 해서 언리얼 프로젝트에 모든 클래스가 언리얼 오브젝트가 되어야 한다는 것은 아닙니다.
일반적으로 입력에 따라 결과 값만 받고 싶은 C++ 클래스도 언리얼 프로젝트에서 전혀 문제 없이 사용할 수 있습니다. 언리얼 엔진에서는 이 둘을 구별하기 위해서 클래스 이름에 붙은 접두사를 사용하는데,
언리얼 오브젝트는 반드시 U로 시작하고 일반 C++ 클래스는 F로 시작하는 것을 권장하고 있습니다.
언리얼 오브젝트는 언리얼 엔진 내에서 객체를 쉽고, 효율적으로 관리하기 위해서 고안되었습니다. C++을 깊숙히 몰라도 언리얼 오브젝트의 성격을 알면 마치 Java나 C#과 같은 언어처럼 사용할 수 있게 되는데요,
C++ 객체가 언리얼 오브젝트가 되면 자동으로 향상되는 기능은 다음과 같습니다.
1.CDO(Class Default Object) : 객체의 초기 값을 자체적으로 관리합니다. 2.Reflection : 객체 정보를 런타임에서 실시간 조회가 가능합니다. 3.GC(Garbage Collection) : 참조되지 않는 객체를 메모리에서 자동 해제할 수 있습니다. 4.Serialization : 객체와 속성 정보를 통으로 안전하게 보관하고 로딩합니다. 5.Delegate : 함수를 묶어서 효과적으로 관리하고 호출할 수 있습니다. 6.Replication : 네트워크 상에서 객체간에 동기화를 시킬 수 있습니다. 7.Editor Integration : 언리얼 에디터 인터페이스를 통해 값을 편집할 수 있습니다.
언리얼 오브젝트 구성 및 생성
언리얼 오브젝트는 C++표준이 아니고, 언리얼 엔진이 자체적으로 만들어 제공하는 프레임웍이기 때문에, 일반적인 방법으로는 만들 수 없고, 언리얼 헤더 툴(Unreal Header Tool)이라는 프로그램의 도움을 받아야 합니다.
여러분들이 헤더 파일에서 클래스 선언을 언리얼 오브젝트 규격에 맞게 선언해주면, 바로 컴파일하는 것이 아닌, 언리얼 헤더 툴이 이를 파싱하고 분석합니다.
헤더 파일의 선언이 규격에 맞지 않으면 언리얼 헤더 툴에 의해 에러가 발생되고,규격에 맞게 선언하였다면, 언리얼 헤더 툴은 부가적인 메타 정보를 담은 소스코드를 프로젝트의 Intermediate 폴더에생성해 줍니다.
이 작업이 모두 끝나면 이제 본격적으로 컴파일을 진행하게 됩니다. 아래는 이러한 구성을 담은 그림입니다.
Ctrl+Alt+F7 키를 눌러 프로젝트를 다시 빌드해봅시다. 다시 출력 로그를 자세히 살펴보면 빌드 과정의 초기에 언리얼 빌드 툴이 동작한다는 로그가 보이게 됩니다.
언리얼 오브젝트 선언규칙
UObject 클래스는언리얼 오브젝트 최상단에 위치한 기본 클래스
이렇다면 이렇게 언리얼 헤더 툴이 인식할 수 있는 언리얼 오브젝트의 선언 규칙은 다음과 같습니다. WebConnection 선언과 한번 비교해보시기 바랍니다.
1. 클래스이름.generated.h를 반드시 가장 마지막에 include 시켜주어야 합니다.
2. 클래스 선언 전에 UCLASS매크로를 사용해야 합니다.
3. 언리얼 오브젝트의 접두사는 U, A 그리고 S가 있습니다. - 액터 기반이라면 A를 - 액터 기반이 아니라면 모두 U - UI를 담당하는 슬레이트만 S를 사용하면 됩니다.
4. UObject 클래스는 언리얼 오브젝트 최상단에 위치한 기본 클래스입니다. 이로 상속받은 클래스는 모두 언리얼 오브젝트가 됩니다.
5. 클래스 선언 내부에 GENERATED_BODY() 매크로도 선언해줍니다.
여기까지는 언리얼 오브젝트를 생성할 때 필수적으로 선언해야 할 규칙이고, 아래와 같이 추가적으로 매크로를 지정해 언리얼 오브젝트를 확장시켜 나갈 수 있습니다
추가 매크로
1. 모듈이름_API 매크로는 상황에 따라 부가 설정을 해주는 매크로입니다. 예를 들어 윈도우 에디터에서 사용할 수 있게 dll로 빌드할 때에는 이 매크로는 MS의 DLL문법인 __declspec(dllexport)구문으로 자동 치환됩니다. 이렇게 선언해야 다른 모듈에서 현재 모듈 내 클래스에 접근할 수 있게 됩니다. 게임 빌드시에는 굳이 외부에 공개할 필요 없이 모든 모듈이 하나의 exe에 통합되므로 이 때는 빈 문자열로 치환됩니다.
2. 언리얼 오브젝트의 생성자는 오브젝트의 기본 값을 지정하는데 사용됩니다. 차후에 설명할 클래스 기본 객체인 CDO를 생성할 때 이 생성자 코드가 한번 실행됩니다.
3. 멤버 변수 위에 UPROPERTY 매크로를 얹어주면 이 변수는 앞으로 언리얼 엔진의 관리를 받게 됩니다. 향후 언리얼 오브젝트가 소멸되더라도 언리얼 엔진의 관리를 받아 해당 멤버 변수의 메모리도 같이 자동으로 소멸되며, 메모리 사용량도 체크할 수 있습니다.
4. 멤버 함수 위에 UFUNCTION 매크로를 얹어주면 블루프린트와 연동되게 할 수 있으며, 딜리게이트나 리플리케이션과 같은 함수를 사용할 수 있어서 멤버 함수의 활용폭이 늘어납니다.
게임인스턴스
시작하면 엔진을 초기화하고 가장 먼저 실행하는 오브젝트 그리고 게임이 종료될 때 까지 GameInstance는 살아있고 프로그램이 종료될 때 가장 마지막에 소멸
이제 처음 시작에 제작한 ArenaBattle 모듈에 있는 ABGameInstance 클래스에 대해 살펴봅시다. ABGameInstance의 클래스 이름 앞에 ‘U’접두사가 붙어 있으니, 이제 우리는 액터가 아닌 언리얼 오브젝트라는 것을 쉽게 파악할 수 있습니다.
사용자가 게임을 시작하면 엔진을 초기화하고 가장 먼저 실행하는 오브젝트가 GameInstance입니다. 그리고 게임이 종료될 때 까지 GameInstance는 살아있고 프로그램이 종료될 때 가장 마지막에 소멸됩니다.
이러한 특징으로 인해 GameInstance의 멤버를 확장해나가면, 게임의 전체 라이프싸이클(LifeCycle)에서 사용되는 데이터를 관리할 수 있습니다.
GameInstance 오브젝트가 초기화될 때, Init이라는 함수를 호출하는데, 이를 상속받으면 우리가 어플리케이션의 초기화 루틴을 만들 수 있게 됩니다.
이제 에디터를 열고 툴바에 있는 [세팅 -> 프로젝트 세팅] 메뉴를 눌러, 프로젝트 설정 다이얼로그를 연 후에 에디터와 게임의 초기화 설정을 주로 지정하는데 사용되는 맵 & 모드로 갑니다.
여기서 하단의 Game Instance Class 항목의 값을 우리가 제작한 ABGameInstance로 변경하면 게임이 시작될 때 ABGameInstance의 인스턴스가 자동 생성되고 이 인스턴스로 어플리케이션이 관리됩니다.
ABGameInstance에서 부모의 Init 함수를 오버라이드(Override)하여 짤막하게 로그를 남기도록 구현해봅시다. 언리얼에서 로그를 남기기 위해서는 언리얼 엔진에서 제공하는 UE_LOG라는 매크로를 사용하면 편리합니다. UE_LOG 매크로는 아래 세 가지 인자로 구성되어 있습니다.
1.Log Category : 로그를 구분할 수 있는 카테고리를 지정합니다. 언리얼 엔진에서는 LogClass , LogTemp와 같은 기본 카테고리를 제공하고 있으며, 모듈마다 로그를 남길 수 있도록 모듈 별로 대부분 카테고리가 지정되어 있습니다. 물론 우리가 원하는 카테고리를 직접 선언할 수 있습니다.
2.Verbosity : Log, Warning, Error로 나뉘며, 각각 흰색, 노란색, 빨간색으로 표시됩니다. Error타입 로그의 경우 프로그램을 멈출 수 있게 설정하는 것도 가능합니다.
3.Format String : C에서 제공하는 Printf 문과 유사하게 사용합니다. 뒤에 Variable Argument를 추가할 수 있으며, 언리얼이 제공하는 2바이트 문자를 지원하는 TEXT 매크로를 사용해 문자열로 로그를 지정하거나 포맷을 정의합니다.
아래는 ABGameInstance 언리얼 오브젝트에 로그를 찍는 기능을 추가한 코드입니다.
우리가 생성하고자 하는 것은 보조 모듈이므로 IMPLEMENT_PRIMARY_GAME_MODULE매크로 대신에 IMPLEMENT_MODULE매크로를 대신 사용합시다.
이 매크로의 첫 번째 인자는 모듈을 관리할 클래스를 지정하는 데 사용합니다. FDefaultModuleImpl은이미 엔진에서 제공하고 있는 모듈 제작을 위한 제공하는 간단한 클래스입니다. 우리는 특별한 모듈을 만들 예정은 없으므로 엔진이 제공하는 구현 클래스를 그대로 사용하겠습니다. 매크로의 두 번째 인자에는 모듈 이름을 넣어주면 됩니다.
여기까지 완성되면 마지막 빌드 규칙인 모듈이름.Build.cs 파일을 추가합니다.
이는 처음부터 직접 만들기 복잡하니 ArenaBattle에 있는 ArenaBattle.Build.cs 파일을 복사해와 이름을 WebService.Build.cs로 변경한 후에 내용만 변경하도록 합시다.
아래는 최종 구성이 완료된 모습입니다.
ArenaBattle.Build.cs 파일을 WebService.Build.cs로 변경한 후에는 파일을 편집해 ArenaBattle로 되어 있는 클래스 이름과 생성자를 모두 새로운 모듈의 이름인 WebService로 교체합니다.
C# 소스 파일과 동일하며, 코드를 보면 PublicDependencyModuleNames와PrivateDependencyModuleNames프로퍼티가 있습니다.
이는 현재 모듈(WebService)이 참조할 외부 모듈의 목록을 지정하는데 사용합니다. 이들 프로퍼티는 각각 Public과 Private 폴더에서 참고할 모듈을 지정하는데 사용됩니다.
처음 사용하는 분들은 이 구조에 대해서 조금 혼동이 있는데, 언리얼 소스 코드 구조는 일반적으로 Public에는 헤더파일을 Private는 소스파일을 넣으므로 처음에는
//WebServiceK.Build.cs
using UnrealBuildTool;
public class WebServiceK : ModuleRules
{
public WebServiceK(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" });
}
}
현재는 Core, CoreUObject, Engine, InputCore 네 가지 모듈이 있는데,
앞의 세 가지는 언리얼 엔진과 연동하는 기능을 만들 예정이라면 거의 대부분 사용해야 할 모듈입니다. 나머지 한 가지는 입력에 관련된 모듈입니다만, 우리는 웹에 접속해서 데이터만 가져올 예정이므로, InputCore 모듈은 제거합시다.
아래는 수정된 최종 WebService.Build.cs 파일의 내용입니다.
//WebServiceK.Build.cs
using UnrealBuildTool;
public class WebServiceK : ModuleRules
{
public WebServiceK(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", });
}
}
모듈에 오브젝트 추가명령 1
이제 탐색기에서 프로젝트 폴더로 돌아가 ArenaBattle.uproject 프로젝트 파일을 우클릭해 Generate Visual Studio project files를 선택해 소스코드를 다시 재생성합시다. 재생성하고 비주얼 스튜디오 솔루션을 다시 열면 아래와 같이 프로젝트의 구성이 업데이트된 것을 볼 수 있습니다.
하지만 빌드를 걸어보면 아래 그림과 같이 아무 반응이 없거나 ArenaBattle에 관련된 바이너리만 빌드가 됩니다.
이는 언리얼 빌드 툴에 의해서 소스 구조는 파악이 되었지만, 빌드할 대상에 우리가 만든 WebService 모듈이 추가되지 않았기 때문입니다.
빌드할 대상 모듈을 지정하는 공간은 프로젝트이름.Target.cs파일입니다. 현재 우리는 게임 빌드와 에디터 빌드가 각각 ArenaBattle.Target.cs 파일과 ArenaBattleEditor.Target.cs 파일에 설정되어 있습니다.
이들을 열고 SetupBinaries 함수의 OutExtraModuelNames 프로퍼티에 우리가 제작한 모듈을 추가합시다.
수정과 저장을 완료한 후, 빌드를 다시 시작하면 비로소 우리가 제작한 모듈을 컴파일하는 것을 볼 수 있을 겁니다.
먼저 빌드 세팅을 Development Editor로 변경한 후에 Ctrl+Alt+F7키를 눌러 "솔루션 다시 빌드 옵션"으로 빌드하면 아래와 같이 에디터용 바이너리로 2개의 dll파일이 생성된 것을 볼 수 있습니다.
모듈에 오브젝트 추가명령 2
우리가제작한모듈이완성된것을확인했으니, 이제 ArenaBattle.uproject를 더블 클릭해 에디터를 실행합시다. 컴파일이 완료됬으니 우리가 제작한 모듈이 에디터에 뜰 것 같았는데, 아쉽게도 목록에 보이질 않습니다.
이는 언리얼 에디터를 가동시킬 때, 언리얼 에디터가 기동할 때, 우리가 새롭게 제작한 모듈을 추가하라는 명령을 uproject 파일에 넣지 않았기 때문입니다.
첫 강좌에서 봤던 uproject 파일의 Modules 항목에 우리가 만든 모듈을 수동으로 추가해주어야, 에디터는 프로젝트의 Binaries 폴더를 뒤져서 우리가 빌드한 모듈을 에디터 프로세스에 포함시켜 띄웁니다.
에디터를 닫고 uproject 파일을 아래와 같이 변경해줍시다.
모듈에 오브젝트 추가명령 3
프로젝트 파일을 변경했음에도 불구하고 여전히 모듈 목록에는 우리가 제작한 모듈 목록이 존재하지 않습니다.
사실 우리가 만든 모듈은 로딩이 되었습니다. 하지만 해당 모듈에는 언리얼 오브젝트라는 객체가 없기 때문에, 목록에서 안 보이는 것 뿐입니다.
에디터에서 새롭게 만든 모듈에 언리얼 오브젝트를 하나 추가해주면 해결됩니다.
에디터를 닫지 말고 파일 메뉴에서 "새로운 C++ 클래스 추가" 메뉴를 눌러서 모든 클래스 표시를 누른 후 최상단에 있는 Object를 선택합시다. Object는 다음 챕터에서 설명할 언리얼 오브젝트의 최상위 기본 클래스입니다.
다음 버튼을 누른 후, 이제 이번 강좌에서 가장 중요한 부분을 진행합시다.
WebConnection이라고 새롭게 생성할 언리얼 오브젝트의 이름을 입력하고, 오른쪽의 모듈 목록을 보면 우리가 만든 WebService라는 모듈이 뜬 것을 볼 수 있습니다. 이를 선택하여, WebConnection 언리얼 오브젝트가 WebService 모듈로 추가되도록 설정합시다.
이제 클래스 생성 버튼을 눌러서 변화를 확인해봅시다. 에디터에서 추가된 모듈의 컴파일을 다시 시작하는데, 현재 환경에 따라 컴파일이 성공할 수도 있고 실패할 수도 있습니다. 결과에 신경쓰지 말고 에디터를 일단 닫읍시다.
다시 비주얼 스튜디오를 살펴보면 WebConnection 헤더파일과 소스파일이 추가된 것을 볼 수 있습니다.
비주얼 스튜디오에서 F7키를 눌러 다시 빌드를 걸어줍시다. 이제 에디터를 다시 실행해보면 드디어 아래와 같이 모듈에 WebService가 새로 생기고 WebConnection이라는 언리얼 오브젝트가 추가된 것을 확인할 수 있습니다.
모듈 폴더의 구성
이제 새로운 모듈의 생성이 성공적으로 완성되었습니다. 하지만 그 전에 모듈 내 파일들을 언리얼 엔진의 구성에 맞게 정리하고 마무리합시다.
언리얼 모듈 폴더의 구성에는 3가지의 특별한 폴더 이름이 존재합니다.
1.Public : 외부 모듈에 공개할 파일을 관리합니다.
2.Private : 내부 모듈에서 사용할 파일을 관리합니다.
3.Classes : Public과 동일합니다만, 주로 프로젝트에서 사용할 언리얼 오브젝트 선언을 별도로 모아 관리합니다. 안 써도 무방합니다.
우리 모듈에도 이 규칙을 적용시킵시다. WebService 폴더에 Public, Private, Classes 폴더를 생성합시다.
현재 모듈 폴더에 있는 파일들을 아래와 같이 각각의 폴더로 옮깁시다.
1.Public 폴더 : WebService.h
2.Private 폴더 : WebService.cpp, WebConnection.cpp
3.Classes 폴더 : WebConnection.h
그리고 다시 프로젝트 폴더의 ArenaBattle.uproject 파일을 우클릭해 Generate Visual Studio project files 메뉴를 선택해 프로젝트를 재생성합시다. 아래는 재생성된 프로젝트의 결과물입니다.
반드시 이렇게 모듈의 폴더 구조를 생성해야 하는 것은 아닙니다. 변경하기 전대로 모듈 폴더에 모든 파일을 몰아넣어도 제작에는 아무 문제 없습니다만, 언리얼 엔진의 소스 코드의 구성이 대부분 이렇게 되어 있습니다.
참고하라는 의미에서 넣었보았습니다. 이제 비주얼 스튜디오에서 F7키를 눌러 최종 빌드를 마무리합시다.