TECHARTNOMAD | TECHARTFLOWIO.COM

TECH.ART.FLOW.IO

[번역][연재물] 언리얼 엔진 개발 가이드. 플러그인 개발

jplee 2025. 6. 6. 17:36

플러그인 개발

플러그인은 엔진과 프로젝트 코드 외부에 있으며, UE에서 프로그램 기능을 확장하는 주요 방법입니다.

플러그인은 본질적으로 모듈화된 코드 설계로, 이 설계를 따르면 코드 간의 의존성을 줄이고 향후 반복 및 유지보수가 쉬워집니다.

UE에서 플러그인의 표준 파일 구조는 다음과 같습니다:

  • Binaries: 컴파일된 생성 파일 저장
  • Content: 플러그인의 에셋 콘텐츠 저장
  • Intermediate: 컴파일 과정에서 생성된 중간 파일 저장
  • Resources: 플러그인의 리소스 파일(아이콘, UE 외 에셋 등) 저장
  • Source: 소스 코드 파일 저장, 다수의 모듈 포함 가능
  • .uplugin: 플러그인의 구조 정의 파일

*.uplugin 파일의 기본 구성은 다음과 같습니다:

{
    "FileVersion": 3,               //파일 버전
    "Version": 1,                   //버전 번호
    "VersionName": "1.0",           //버전 이름
    "FriendlyName": "CustomPlugin", //별칭
    "Description": "",              //설명
    "Category": "Other",            //카테고리
    "CreatedBy": "",                //제작자
    "CreatedByURL": "",             //제작자 URL
    "DocsURL": "",                  //문서 URL
    "MarketplaceURL": "",           //마켓플레이스 URL
    "SupportURL": "",               //지원 URL
    "CanContainContent": false,     //콘텐츠 디렉토리 포함 여부
    "IsBetaVersion": false,         //베타 버전 여부
    "IsExperimentalVersion": false, //실험적 버전 여부
    "Installed": false,             //내장 여부
    "Modules": [                    //모듈 정의
        {
            "Name": "CustomPlugin",     //모듈 이름
            "Type": "Editor",           //모듈 타입
            "LoadingPhase": "Default"   //로딩 시점
        }
        //,                             //기타 모듈
        //{
        //  ...    
        //}
    ]
}

이러한 매개변수의 구성에 대한 자세한 내용은 다음을 참조하십시오:

UE에서 플러그인을 개발할 때의 일반적인 워크플로우는 다음과 같습니다:

  • 먼저 편집 - 플러그인을 클릭하여 플러그인 패널을 엽니다

새 플러그인 추가

빈 플러그인 생성

  • 프로젝트 구조가 변경되었으므로 IDE 프로젝트 파일을 다시 생성해야 합니다

빈 플러그인은 좋은 시작점입니다. 다른 플러그인들은 단지 추가적인 코드 템플릿이 포함된 것뿐입니다. 익숙하지 않다면 추가해보면서 어떤 코드가 추가되었는지 파악하고, 그 기능을 이해한 후 빈 플러그인에 필요한 기능을 추가하면 됩니다

다음은 C++ 플러그인에 반드시 포함되어야 하는 파일입니다:

// MyPlugin.h
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class FMyPluginModule : public IModuleInterface
{
public:
    /** IModuleInterface implementation */
    virtual void StartupModule() override;
    virtual void ShutdownModule() override;
};

// MyPlugin.cpp
#include "MyPlugin.h"
#define LOCTEXT_NAMESPACE "FMyPluginModule"
void FMyPluginModule::StartupModule()
{
    // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FMyPluginModule::ShutdownModule()
{
    // This function may be called during shutdown to clean up your module.  For modules that support dynamic reloading,
    // we call this function before unloading the module.
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FMyPluginModule, MyPlugin)     //플러그인 항목 정의

UE는 플러그인 로드 시 StartupModule()을 호출하고, 언로드 시 ShutdownModule()을 호출합니다.

플러그인 개발의 주요 코드 흐름은 다음과 같습니다:

  • StartupModule()에서는 코어 모듈의 함수 인터페이스를 호출하거나 코어 모듈의 전역 싱글톤을 사용하여 작업을 수행하거나, 코어 모듈의 진입점에 로직을 연결하여 기능을 확장합니다.
  • ShutdownModule()에서는 StartupModule()에서 수행한 작업들을 정리합니다

자주 사용되는 함수 모듈은 다음과 같습니다:

  • FFileHelper: 파일 작업
  • FPlatformProcess: 플랫폼 관련 작업
  • FBlueprintEditorUtils: 블루프린트 작업
  • FKismetEditorUtilities: 에디터 작업
  • FEdGraphUtilities: 그래프 작업
  • FComponentEditorUtils: 컴포넌트 에디터 작업
  • FEnumEditorUtils: 열거형 작업
  • FStructureEditorUtils: 구조체 작업
  • FEditorFolderUtils: 에디터 폴더 작업
  • FMaterialEditorUtilities: 머티리얼 작업
  • FPluginUtils: 플러그인 작업
  • UGameplayStatics: 게임플레이 관련 작업
  • ...

전역 싱글톤은 다음과 같습니다:

  • GEngine, GEditor, GWorld: 엔진에서 자주 사용되는 전역 싱글톤
  • FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools").Get(): 에셋의 생성, 삭제, 이름 변경, 가져오기/내보내기...
  • FModuleManager::LoadModuleChecked<FAssetRegistryModule>(TEXT("AssetRegistry")).Get(): 에셋의 검색, 열거...
  • FModuleManager::LoadModuleChecked<ISettingsModule>("Settings"): 설정 파일 관련 관리
  • FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor"): 프로퍼티 에디터 관련 작업
  • FModuleManager::LoadModuleChecked<FLevelEditorModule>(TEXT("LevelEditor")): 레벨 에디터 관련 작업
  • FModuleManager::LoadModuleChecked<FBlueprintEditorModule>("Kismet"): 블루프린트 에디터 관련 작업
  • ...

코어 모듈의 진입점은 일반적으로 다음을 의미합니다:

  • Callback 함수 콜백
  • Delegate 델리게이트

일반적인 델리게이트 정의 모음은 다음과 같습니다:

  • FCoreUObjectDelegates: UObject 관련 델리게이트
  • FCoreDelegates: 코어 모듈 관련 델리게이트
  • FEditorDelegates: 에디터 모듈 관련 델리게이트
  • FWorldDelegates: 게임 월드 관련 델리게이트
  • FGameDelegates
  • ...

플러그인 작성을 완료하고 컴파일을 실행하면 플러그인의 Binaries 디렉토리에 다음 파일들이 생성됩니다:

  • .module: 모듈 라이브러리의 기본 정보를 정의
  • .dll: 동적 라이브러리
  • .pdb: 프로그램 디버깅 데이터베이스, 소스 코드를 통한 브레이크포인트 디버깅에 사용됨. 자세한 내용은 여기 참조

*.module 파일의 내용은 다음과 같습니다

{ "BuildId": "a36b278a-b317-44c3-8743-b82361b74343", "Modules": { "MyPlugin": "UnrealEditor-MyPlugin.dll" } }

여기서 주의해야 할 매개변수는 BuildID입니다. 이는 엔진에서 생성되며, 플러그인의 BuildID가 엔진의 BuildID와 일치하지 않을 경우 에디터에서 프로젝트 실행 시 오류가 발생합니다:

엔진의 빌드 ID를 볼 수 있습니다:

기본

메뉴바 및 툴바 확장

엔진 개발 과정에서 편집기의 메뉴바와 툴바를 확장하여 버튼을 추가하고 편리한 기능을 실행하는 등의 요구사항이 자주 발생합니다. 다음과 같은 방식으로 구현할 수 있습니다:

UE4에서는 메뉴 확장의 주요 방식이 FExtender를 통해 이루어졌으나, UE5에서는 보다 사용하기 쉬운 새로운 방식인 UToolMenus가 도입되었습니다.

  • UToolMenus는 싱글톤 클래스로, 다음 코드를 통해 싱글톤 인스턴스를 얻을 수 있습니다:

UToolMenus* ToolMenus = UToolMenus::Get();

UE5에서는 모든 확장 가능한 메뉴바와 툴바가 초기화 시 UToolMenus::RegisterMenu 함수를 호출하여 등록됩니다:

UToolMenu* UToolMenus::RegisterMenu(const FName InName,
                                    const FName InParent = NAME_None,
                                    EMultiBoxType InType = EMultiBoxType::Menu,
                                    bool bWarnIfAlreadyRegistered = true)

이 함수는 확장 가능한 ToolMenu를 등록하는 데 사용되며, 함수의 각 매개변수는 다음과 같습니다:

  • InName: 등록에 사용되는 체인 필드로, LevelEditor.LevelEditorToolBar.User와 같은 형식입니다. 이후 이 필드를 키로 사용하여 UToolMenu를 얻을 수 있습니다
  • InParent: 도구 메뉴의 상위 항목을 지정
  • InType: 해당 ToolMenu의 유형을 지정하며, 이 유형에 따라 메뉴를 확장하는 방법이 결정됩니다. 다음과 같은 값을 사용할 수 있습니다:
    • MenuBar: 메뉴 바, 메뉴 확장 지원
    • ToolBar: 도구 모음, 도구 버튼 추가 가능
    • VerticalToolBar: 수직 도구 모음
    • SlimHorizontalToolBar: 수평 도구 모음, 도구 모음의 간소화 버전으로 아이콘과 텍스트 요소를 수평 정렬할 수 있음
    • UniformToolBar:
    • Menu: 메뉴, 메뉴 항목 추가 가능
    • ButtonRow: 행으로 배열된 버튼, 행당 최대 버튼 수가 있으며 도구 모음과 유사하지만 여러 행을 가질 수 있음
  • bWarnIfAlreadyRegistered: Bool 값, 해당 필드가 이미 등록되어 있을 경우 경고를 발생시킴

메뉴 미리보기가 필요한 시점에는 UToolMenus::GenerateWidget 함수를 호출하여 ToolMenu 위젯을 생성합니다:

TSharedRef<SWidget> UToolMenus::GenerateWidget(const FName Name, const FToolMenuContext& InMenuContext)

ToolMenu가 Register된 후, 미리보기 전 어느 시점에서든 UToolMenus::ExtendMenu 함수를 통해 메뉴바의 내용을 확장할 수 있습니다.

위 코드에는 많은 확장자 참조가 있으며, 다음은 간단한 플러그인 확장자의 예입니다:

#pragma once
#include "Modules/ModuleManager.h"
class FCustomPluginModule : public IModuleInterface
{
public:
    virtual void StartupModule() override {
        //启动插件时给UToolMenus的启动增加一个回调
        UToolMenus::RegisterStartupCallback(FSimpleMulticastDelegate::FDelegate::CreateRaw(this, &FCustomPluginModule::RegisterMenus));
    }
    virtual void ShutdownModule() override {
        //去除UToolMenus的启动回调,重置一些状态
        UToolMenus::UnRegisterStartupCallback(this);
        UToolMenus::UnregisterOwner(this);
    }
private:
    void RegisterMenus() {
        FToolMenuOwnerScoped OwnerScoped(this);
        UToolMenu* Menu = UToolMenus::Get()->ExtendMenu("LevelEditor.LevelEditorToolBar.PlayToolBar");
        FToolMenuSection& Section = Menu->FindOrAddSection("PluginTools");
        FToolMenuEntry& MenuEntry = Section.AddEntry(
            FToolMenuEntry::InitToolBarButton(          //도구 모음 버튼 추가
                "CustomToolbarButton",
                FUIAction
                (
                    FExecuteAction::CreateLambda([]() {
                        FMessageDialog::Open(EAppMsgType::Ok, NSLOCTEXT("CustomNs", "HelloWorld", "Hello World!"));
                    })
                )
            )
        );
        MenuEntry.InsertPosition = FToolMenuInsert(NAME_None, EToolMenuInsertType::First);
    }
};

이 코드는 레벨 에디터 메인 패널의 툴바에 버튼을 추가하며, 클릭 시 Hello World 대화상자가 표시됩니다:

UToolMenus::Get()에 브레이크포인트를 추가하여 VS 디버그 창을 통해 모든 확장 가능한 필드 목록을 확인할 수 있습니다:

에셋 확장

뷰포트 확장

뷰포트를 확장하기 위해서는 다음과 같은 구조체들이 필요합니다

  • SEditorViewport
  • FEditorViewportClient

디테일 패널 관련

DetailView는 UE 리플렉션이 제공하는 또 다른 강력한 기능입니다:

블루프린트 확장

사용자 경험

실행 취소/다시 실행

UObject는 트랜잭션 메커니즘을 가지고 있으며, UObject가 RF_Transactional 플래그를 가지고 있다면 다음과 같은 코드를 사용할 수 있습니다:

GEditor->BeginTransaction(NSLOCTEXT("NS", "Transaction", "Transaction"));       //트랜잭션 시작
Object->Modify();               //이 작업은 Object의 현재 상태를 트랜잭션에 저장
SomeChange(Object);             //Object의 일부 속성 수정
GEditor->EndTransaction();      //트랜잭션 종료, Object的新状态

위 작업을 통해 SomeChanged 작업을 실행 취소/다시 실행할 수 있습니다.

자세한 내용은 다음을 참조하세요: https://blog.csdn.net/qq_29523119/article/details/96778797

에디터 개발 시 특정 객체나 창이 실행 취소/다시 실행될 때 변경 사항에 응답해야 하는 경우가 자주 있습니다(예: 일부 재구성 수행). UE는 실행 취소/다시 실행 이벤트를 모니터링하기 위한 FEditorUndoClient 인터페이스를 제공하며, 다음은 간단한 코드 예시입니다:

class FUndoRedoListener: public FEditorUndoClient{
public:
    FUndoRedoListener(){
        if (GEditor)
            GEditor->RegisterForUndo(this);     //적절한 시점에 리스너 등록, 반드시 생성자에서 할 필요는 없음
    }
    ~FUndoRedoListener(){
        if (GEditor)
            GEditor->UnregisterForUndo(this);   //등록 해제
    }
protected:
    virtual void PostUndo(bool bSuccess) override{      //에디터에서 실행 취소 수행 후 호출되는 함수
        RebuildSomething();
    }
    virtual void PostRedo(bool bSuccess) override{      //에디터에서 다시 실행 수행 후 호출되는 함수
        RebuildSomething();   }
};

사용자 피드백

알림

FNotificationInfo Info(FText::FromString(TEXT("This is notification")));
Info.FadeInDuration = 2.0f;
Info.ExpireDuration = 2.0f;
Info.FadeOutDuration = 2.0f;
FSlateNotificationManager::Get().AddNotification(Info);

static TWeakPtr<SNotificationItem> NotificationPtr;
FNotificationInfo Info(FText::FromString(TEXT("This is notification")));
Info.FadeInDuration = 2.0f;
Info.FadeOutDuration = 2.0f;
Info.bFireAndForget = false;        
Info.bUseThrobber = false;
FNotificationButtonInfo BtYesInfo = FNotificationButtonInfo(
    NSLOCTEXT("NotificationNamespace","Yes", "Yes"),
    NSLOCTEXT("NotificationNamespace","Yes", "Yes"),
    FSimpleDelegate::CreateLambda([]() {
        TSharedPtr<SNotificationItem> Notification = NotificationPtr.Pin();
        if (Notification.IsValid())
        {
            Notification->SetEnabled(false);
            Notification->SetExpireDuration(0.0f);
            Notification->ExpireAndFadeout();   
            NotificationPtr.Reset();
        }
    }),
    SNotificationItem::ECompletionState::CS_None
);
Info.ButtonDetails.Add(BtYesInfo);
NotificationPtr = FSlateNotificationManager::Get().AddNotification(Info);

진행률 표시기

float AmountOfWork = 50;
FScopedSlowTask RootTask(AmountOfWork, (NSLOCTEXT("SlowTaskNamespace", "This is slow root task", "This is slow root task")));
RootTask.MakeDialog();
for (int i = 0; i < 50; i++) {
    FScopedSlowTask SubTask(1, (NSLOCTEXT("SlowTaskNamespace", "This is slow sub task", "This is slow sub task ")));
    SubTask.MakeDialog();
    for (int j = 0; j < 2; j++) {
        FPlatformProcess::Sleep(0.5);
        SubTask.EnterProgressFrame(0.5, FText::FromString("Sub Task"));
    }
    RootTask.EnterProgressFrame(1, FText::FromString("Root Task"));
}

다이얼로그

EAppReturnType::Type Ret = FMessageDialog::Open(EAppMsgType::YesNo, NSLOCTEXT("NS", "message dialog", "message dialog"));
if (Ret == EAppReturnType::Yes) {   
}

기본 조작

문자열

TCHAR

일반적으로 코드의 문자열은 ANSI로 인코딩되지만, ANSI는 지원하는 문자 수가 적기 때문에 문자열 변수를 설정할 때 TEXT() 매크로를 사용하여 ANSI 문자를 TCHAR(네이티브 유니코드 인코딩)로 변환해야 합니다.

TCHAR* ThisIsTChars = TEXT("This is Raw String");

TCHAR와 네이티브 문자열 인코딩 형식을 변환하려면 다음 매크로를 사용할 수 있습니다:

  • TCHAR_TO_ANSI (str)
  • TCHAR_TO_UTF8 (str)
  • TCHAR_TO_UTF16 (str)
  • TCHAR_TO_UTF32 (str)
  • TCHAR_TO_WCHAR (str)
  • ANSI_TO_TCHAR (str)
  • UTF8_TO_TCHAR (str)
  • ...

게임은 성능에 대한 요구사항이 매우 높으며, 일반 String으로는 UE 게임 개발의 다양한 사용 사례에서 요구되는 성능을 만족시킬 수 없습니다. 따라서 UE4는 세 가지 주요 문자열 클래스를 제공합니다:

FString

일반 문자열로, 수정 가능하며 문자열을 조작하는 다양한 메서드를 제공합니다.

  • 생성
    • static FString Chr ( TCHAR Ch )
    • static FString ChrN ( int32 NumCharacters, TCHAR Char )
    • static FString FromInt ( int32 Num )
    • static FString SanitizeFloat ( double InFloat, const int32 InMinFractionalDigits = 1 )
    • static FString FromBlob (const uint8* SrcBuffer,const uint32 SrcSize);
  • 포맷
    • static FString Printf (const FmtType& Fmt, Types... Args)
    • FString& Appendf (const FmtType& Fmt, Types... Args)
    • static FString Format (const TCHAR* InFormatString, const FStringFormatOrderedArguments& InOrderedArguments)
    • static FString Format (const TCHAR* InFormatString, const FStringFormatNamedArguments& InNamedArguments)
  • 변환
    • void ToUpperInline ()
    • FString ToUpper ()
    • void ToLowerInline ()
    • FString ToLower ()
  • 일치
    • bool Equals (const FString& Other, ESearchCase::Type SearchCase = ESearchCase::CaseSensitive)
    • int32 Compare ( const FString& Other, ESearchCase::Type SearchCase = ESearchCase::CaseSensitive ) const
    • bool IsNumeric ()
    • bool StartsWith (const FString& InPrefix, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase)
    • bool EndsWith (const FString& InSuffix, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase )
    • bool MatchesWildcard (const FString& Wildcard, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase)
    • bool Contains (const TCHAR* SubStr, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase, ESearchDir::Type SearchDir = ESearchDir::FromStart )
  • 트림
    • void TrimStartAndEndInline ()
    • FString TrimStartAndEnd ()
    • void TrimStartInline ()
    • FString TrimStart ()
    • void TrimEndInline ()
    • FString TrimEnd ()
    • void TrimQuotesInline (bool* bQuotesRemoved = nullptr);
    • FString TrimQuotes (bool* bQuotesRemoved = nullptr)
    • void TrimCharInline (const TCHAR CharacterToTrim, bool* bCharRemoved)
    • FString TrimChar (const TCHAR CharacterToTrim, bool* bCharRemoved = nullptr)
  • 찾기
    • int32 Find ( const TCHAR* SubStr, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase, ESearchDir::Type SearchDir = ESearchDir::FromStart, int32 StartPosition=INDEX_NONE )
    • bool FindChar ( TCHAR InChar, int32& Index )
    • bool FindLastChar ( TCHAR InChar, int32& Index )
    • int32 FindLastCharByPredicate (Predicate Pred, int32 Count)
    • int32 FindLastCharByPredicate (Predicate Pred)
  • 파싱
    • int32 ParseIntoArray ( TArray& OutArray, const TCHAR* pchDelim, bool InCullEmpty = true )
    • bool Split (const FString& InS, FString* LeftS, FString* RightS, ESearchCase::Type SearchCase, ESearchDir::Type SearchDir = ESearchDir::FromStart)
  • 분할
    • void LeftInline (int32 Count, bool bAllowShrinking = true)
    • FString Left ( int32 Count )
    • void LeftChopInline (int32 Count, bool bAllowShrinking = true)
    • FString LeftChop ( int32 Count )
    • FString Right ( int32 Count )
    • void RightInline (int32 Count, bool bAllowShrinking = true)
    • FString RightChop ( int32 Count )
    • void RightChopInline (int32 Count, bool bAllowShrinking = true)
    • FString Mid (int32 Start, int32 Count)
    • void MidInline (int32 Start, int32 Count = MAX_int32, bool bAllowShrinking = true)
  • 결합
    • static FString Join (const RangeType& Range, const TCHAR* Separator)
    • static FString JoinBy (const RangeType& Range, const TCHAR* Separator, ProjectionType Proj)
  • 치환
    • FString Replace (const TCHAR* From, const TCHAR* To, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase)
    • int32 ReplaceInline ( const TCHAR* SearchText, const TCHAR* ReplacementText, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase )
    • FString ReplaceQuotesWithEscapedQuotes ()
    • void ReplaceCharWithEscapedCharInline ( const TArray* Chars = nullptr )
    • FString ReplaceCharWithEscapedChar ( const TArray* Chars = nullptr )
    • void ReplaceEscapedCharWithCharInline ( const TArray* Chars = nullptr )
    • void ConvertTabsToSpacesInline (const int32 InSpacesPerTab);
    • FString ConvertTabsToSpaces (const int32 InSpacesPerTab)
  • 뒤집기
    • void ReverseString ();
    • FString Reverse ()

FText

텍스트 현지화(다국어)를 지원하므로, 사용자에게 표시되는 모든 텍스트는 이것을 사용해야 합니다

텍스트 현지화(국제화)

FName

이름을 지정하는 데 사용되며 대소문자를 구분하지 않습니다. 리소스를 빠르게 찾기 위해 FName은 생성 시 문자열 내용을 기반으로 해시 값을 계산합니다. 이를 통해 비교 로직 수행 시 문자열 내용을 비교하지 않고 해시 값의 일치 여부만 확인하면 됩니다.

상호 변환

TestString = TestName.ToString();
TestString = TestText.ToString();
TestName = FName(*TestString);
TestName = TestText    // FText에서 FName으로의 직접 변환은 없으나, FString을 거쳐 FName으로 변환할 수 있습니다. 단, FName이 대소문자를 구분하지 않아 신뢰성이 떨어집니다.
TestText = FText::FromName(TestName)
TestText = FText::FromString(TestString)

경로

FPaths

FPackagePath

정규식 (Math)

https://blog.csdn.net/justtestlike/article/details/81393221

Math

UE의 Math 함수는 다음 두 네임스페이스에 있습니다:

  • FMath: UE의 기본 수학 라이브러리
  • UkismetMathLibrary: 블루프린트 라이브러리로, FMath를 기반으로 블루프린트에 노출되는 수많은 함수를 캡슐화합니다.

시간 및 날짜

타이머

파일 작업

입출력

FArchive

파일

UE에서는 싱글톤 클래스 IFileManager를 통해 다양한 파일 작업을 제공하며, 다음과 같은 기능들을 포함합니다:

  • 파일의 읽기/쓰기, 이동, 삭제, 존재 여부 확인, 읽기 가능 여부 확인, 검색(재귀)
  • 디렉토리 생성, 삭제, 존재 여부 확인, 순회

파일 IO의 경우, FFileHelper에서 일회성 파일 읽기/쓰기를 위한 편리한 정적 메서드들을 제공합니다.

바이트 스트림

이미지

직렬화

Json

자세한 참조:https://www.cnblogs.com/shiroe/p/14751769.html

XML

멀티스레딩

FThread, FRunnable

FStreamManager

AsyncTask

TaskGraph

디버깅

로그

  • 사용자 정의 로그 카테고리// 헤더 파일에서 선언 DECLARE_LOG_CATEGORY_EXTERN(CustomLogCategory, Log, All);// 소스 파일에서 정의 DEFINE_LOG_CATEGORY(CustomLogCategory);
  • 로그 출력UE_LOG(CustomLogCategory,Log,TEXT("This is log %d"),123);
    • Log
    • Warning
    • Error

ASSERTION

코드는 다음 위치에 있습니다.:Engine\Source\Runtime\Core\Public\Misc\AssertionMacros.h

  • checkCode
  • check
  • checkf
  • checkNoEntry
  • checkNoReentry
  • checkNoRecursion
  • verify
  • verifyf
  • unimplemented
  • ensure
  • ensureMsgf
  • ensureAlways
  • ensureAlwaysMsgf

성능 분석

콘솔 명령어

모델링 도구

void UBPLibrary::SetStaticMeshPivot(UStaticMesh* InStaticMesh, EStaticMeshPivotType PivotType)
{
    if(InStaticMesh == nullptr)
        return;
    auto InteractiveToolsContext = NewObject<UEditorInteractiveToolsContext>();
    InteractiveToolsContext->InitializeContextWithEditorModeManager(&GLevelEditorModeTools(), nullptr);
    UE::TransformGizmoUtil::RegisterTransformGizmoContextObject(InteractiveToolsContext);
    InteractiveToolsContext->ToolManager->RegisterToolType("EditPivotTool", NewObject<UEditPivotToolBuilder>());
    UStaticMeshComponent* StaticMeshComp = NewObject<UStaticMeshComponent>();
    StaticMeshComp->SetStaticMesh(InStaticMesh);
    InteractiveToolsContext->TargetManager->AddTargetFactory(NewObject<UStaticMeshComponentToolTargetFactory>());
    UToolTarget* Target = InteractiveToolsContext->TargetManager->BuildTarget(StaticMeshComp, FToolTargetTypeRequirements());
    InteractiveToolsContext->ToolManager->SelectActiveToolType(EToolSide::Left, "EditPivotTool");
    GLevelEditorModeTools().SelectNone();
    GLevelEditorModeTools().GetSelectedComponents()->Select(StaticMeshComp);
    InteractiveToolsContext->ToolManager->ActivateTool(EToolSide::Left);
    if (auto EditTool = Cast<UEditPivotTool>(InteractiveToolsContext->ToolManager->ActiveLeftTool))
    {
        EditTool->SetTargets({ Target });
        EditTool->RequestAction((EEditPivotToolActions)PivotType);
        EditTool->Tick(0.1);
        EditTool->Shutdown(EToolShutdownType::Accept);
    }
}