[UE4] 모듈(Module), 디버그 모드 카테고리 추가하기, 스마트 포인터(Shared Point, Shared Referrence, Unique Point, Weak Pointer)
💡 모듈(Module)
C에서는 독자적인 기능을 모아둔 것을 라이브러리라고 표현하지만, 언리얼에서는 라이브러리가 아닌 모듈(Module)이라고 표현한다.
가장 먼저, FExampleModule이라는 플러그인을 하나 만들어보았다.
기본 플러그인으로 플러그인을 생성하면
위와 같은 헤더파일이 생성된다.
모듈이 실행될 때 StartupModule() 함수가 실행되고, 모듈이 종료될 때 자동으로 ShutdownModule() 함수가 실행된다. 따라서 StartupModule() 함수가 Entry Point(진입점)이고 ShutdownModule() 진출점?이다.
진입점을 가지고 있는 클래스는 무조건 IModuleInterface 를 상속받고 있어야하는데 이러한 클래스를 언리얼은 IMPLEMENT_MODULE(FExampleModule, Example) 매크로로 찾는다. Example은 uplugin 파일에 정의되어 있는 모듈명이다.
즉, 매크로의 의미는 Example 모듈을 실행시킬 것인데 어디 클래스에 있느냐 (FExampleModule)를 의미하여 찾는 것이다.
#define LOCTEXT_NAMESPACE "FExampleModule" 는 LOC가 Locale인 지역을 의미하여 국가적인 텍스트 현지화를 실행시킨다. 즉, 국가별로 알맞은 텍스트를 지원해주기 위해 사용한다.
텍스트 현지화에서 더 나아가 스트링 테이블은 현지화 된 텍스트를 Table로 묶어주는 역할을 수행한다.
💡 디버그 모드 추가하기
반 따옴표 ( ' )를 눌렀을 때 뷰포트에 나오는 디버그 메뉴들을 IGameplayDebugger 클래스를 이용하여 플러그인을 통해 추가할 수 있다.
클래스명 앞에 I 가 붙었으므로 인터페이스인데, 언리얼은 순수가상함수가 존재하지 않고 static 함수가 정의되어 있어도 인터페이스이다.
IGameplayDebugger의 Get 함수를 사용하면 디버그 모드에 있는 메뉴들, 즉 모듈들을 모두 불러올 수 있다.
이렇게 Get 함수를 사용하여 IGameplayDebugger를 불러왔다.
또한 에디터는 거의 대부분이 이벤트 기반인 델리게이트로 이루어져 있다.
IGameplayDebugger에 FOnGetCategory 라는 델리게이트에 접근하여 새로운 카테고리를 생성해보았다.
Return 값으로 TSharedRef 형인 스마트 포인터를 반환한다.
💡 스마트 포인터
Shared Point는 일반적으로 쓰는 포인터를 스마트 포인터로 관리해주는 역할을 수행하고, Shared Referrence는 공유할 수 있는 레퍼런스 Shared Point로 비슷하다.
Unique Point는 공유 불가능하여 하나만 사용할 수 있다.
Weak Pointer는 Shared Point와 비슷하지만 참조하는 오브젝트를 소유하지 않기 때문에 생명 주기에 영향을 주지 않는다. 즉, Weak Pointer는 언제 제거될 지 모르기 때문에 가비지 콜렉터에 의해 Weak Pointer가 제거되면 안된다.
나머지 더 자세한 설명은 언리얼 엔진 문서에서 제공하는 위 내용들을 참고하면서 공부하자.
다시 돌아가 FOnGetCategory 델리게이트에 등록할 함수로 static 함수를 등록하였다.
static 함수를 생성할 C++ 클래스를 새로 제작하였는데, 엔진에서 C++ 클래스의 상속 리스트에는 UObject 하위의 클래스들만 나오기 때문에 모듈의 클래스를 만들기 위해 상속 받을 클래스를 "없음"으로 설정한 뒤 FExampleDebuggerCategory 클래스를 생성하였다.
FGameplayDebuggerCategory를 상속받아 TSharedRef를 반환하는 MakeInstance 함수를 정의하였다.
Shared Pointer는 TSharedPtr<AActor> actor = &player; 와 같이 그냥 주소를 넣어 초기화하면 되지만
Shared Refference는 MakeShareable 함수를 이용하여 만든다. 쉐어드 레퍼런스는 객체를 소유해야 하기 때문에 new 키워드로 객체를 만들어 매개변수로 전달해주었다.
언리얼에서 new 키워드를 사용하면 안되지만 에디터에서는 상관없이 사용할 수 있다.
이렇게 만들어진 MakeInstance 함수를 FOnGetCategory의 CreateStatic 함수로 등록시켜주었다.
이때의 델리게이트를 category라는 변수로 저장하여 필요할 때 Call 할 수 있도록 하였다.
debugger는 게임에서 단 하나만 실행되기 때문에 싱글톤으로 이루어져 있어 Get 함수를 통해 사용해야한다.
RegisterCategory 함수를 이용하면 디버그 모드에 카테고리를 등록할 수 있다. "Example" 이라는 이름으로 카테고리를 등록하였고 Category State를 Enabled In Game And Simulate로 설정하여 게임모드와 시뮬레이트 모드 둘다 카테고리를 사용할 수 있도록 하였다.
마지막으로 NotifyCategoriesChanged 함수를 사용하여 카테고리가 변경될 때 마다 노티파이를 호출하도록 하였다.
이후 Build.cs 클래스에 사용하려는 모듈을 PrivateDependencyModuleNames에 추가해주어야 성공적으로 모듈을 사용하여 링크에러가 발생하지 않는다.
결과적으로 디버그 모드에 카테고리로 Example이 추가된 것을 확인할 수 있다.
참조
언리얼 스마트 포인터 라이브러리
위크 포인터 및 Null이 불가능한(non-nullable) 쉐어드 레퍼런스와 같은 쉐어드 포인터들의 커스텀 구현입니다.
docs.unrealengine.com