구현 목표
언리얼 에디터를 사용하다보면 ‘이러한 기능이 있으면 좋을 것 같다’ 혹은 ‘반복적인 작업을 좀 더 쉽게 하고 싶다’는 생각이 들었습니다. 그래서 언리얼 에디터를 확장해보는 것을 목표로 삼았습니다.
엔진 버전은 5.3입니다.
구현 과정
1) 정의
들어가며
아시다시피 언리얼 엔진은 여러 개의 모듈로 구성된 집합체입니다. 이 중에서 우리는 에디터 모듈을 사용할 거에요. 모듈과 에디터 확장에 대한 부분을 조금 설명해야 하지만 아래 링크로 대체하겠습니다. 저보다 이득우 교수님이 설명을 훨씬 더 잘해놓으셔서…👍
📌 언리얼 에디터 확장에 대한 이득우 교수님의 IGC 강의 내용입니다.
[IGC2018] 청강대 이득우 - 언리얼에디터확장을위해알아야할것들
사전 준비
- 플러그인을 하나 만들거에요. Blank로 선택하시고, 이름을 정해주세요. (저는
RealXtension으로 지었습니다.)

{
"FileVersion": 3,
"Version": 1,
"VersionName": "1.0",
"FriendlyName": "RealXtension",
"Description": "",
"Category": "Other",
"CreatedBy": "Xerlock",
"CreatedByURL": "",
"DocsURL": "",
"MarketplaceURL": "",
"SupportURL": "",
"CanContainContent": true,
"IsBetaVersion": false,
"IsExperimentalVersion": false,
"Installed": false,
"Modules":
[
{
"Name": "RealXtension",
"Type": "Editor",
"LoadingPhase": "PreDefault"
}
]
}
- 생성이 완료 되었다면 몇 가지 설정을 해주셔야 합니다.
- 생성하신 플러그인에서
uplugin확장자를 찾아서 파일을 열어주세요. Type과LoadingPhase를 바꿔주세요.- 에디터에서 사용할 것이기 때문에 Editor로, 에디터가 로드되기 전에 로드되어야 하므로 PreDefault로 바꿔주는 작업입니다.
2) 분석
Built-in Class
언리얼에서는 에디터 확장을 쉽게 할 수 있도록 미리 제공하는 유틸 클래스가 있어요.
AssetActionUtility: Asset action에 관련된 유틸 클래스ActorActionUtility: Actor action에 관련된 유틸 클래스
만약 만들 기능이 Asset을 CRUD 하면 AssetActionUtility
그게 아닌 Actor를 다루는 일이라면 ActorActionUtility를 사용하면 됩니다.
제가 이번에 만들 기능은 Assest을 다루기 때문에 AssetActionUtility 를 사용해보도록 하겠습니다.


- 새 C++ 클래스 생성을 눌러
AssetActionUtility를 생성합니다. - 기존의 프로젝트 위치가 아닌 플러그인 위치로 변경합니다.
..\RealXtension\Public\AsssetActions\QuickAssetAction.h
모듈 추가
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "AssetActionUtility.h" // Error !
#include "QuickAssetAction.generated.h"
/**
*
*/
UCLASS()
class REALXTENSION_API UQuickAssetAction : public UAssetActionUtility
{
GENERATED_BODY()
};
클래스를 생성하고 헤더 파일을 보시면 2번째 인크루드에서 오류가 발생합니다.
이 헤더를 프로젝트에서 찾아보면 옆의 그림과 같은 경로에 있는 것을 볼 수 있어요.
Source/Editor/Blutility/Classes/AssetActionUtility.h
이는 의존성 모듈에 의해 발생하는 것으로 해당 클래스의 의존성 모듈을 Build.cs 에 추가해주면 됩니다.
! Plugin의 Build.cs에 추가하셔야 합니다 !

PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"Blutility"
// ... add other public dependencies that you statically link with here ...
}
);
Scripted Asset Action
지금까지 제대로 따라왔다면 컴파일이 정상적으로 될 거에요. 그렇다면 이제 화면에 디버그 메시지를 띄워보도록 할게요.
먼저
DebugFunc라는 함수를 하나 만들어주겠습니다.함수에
UFUNCTION(CallInEditor)라는 매크로를 선언해주세요.- CallInEditor는 디테일 패널에서 이 함수가 보여지도록 만들어줘요.
함수 구현부에서 다음과 같은 코드를 입력해주세요.
if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 8.f, FColor::Cyan, TEXT("Debug On Text")); }
이제 에디터에서 블루프린트를 하나 생성하고 마우스 오른쪽 버튼을 눌러 Scripted Asset Actions 의 Debug Func를 눌러보세요. 아마 에디터의 뷰포트에 메시지가 출력되는 것을 볼 수 있을겁니다.


📌 만약
Scripted Asset Actions이 보이지 않는다면 아래를 참고 해주세요.
Scripted Asset Actions이 안보여요
5.0 버전은 확인을 했는데, 그 이후 버전에서는 따로 에디터 유틸리티 블루프린트를 생성해줘야합니다. 그 내용은 다음과 같습니다.
생성하신 플러그인의 Content 폴더에서
Editor Utility Blueprint를 생성해주세요.
생성하신 블루프린트를 열고
Parent Class를 방금 만드신 클래스로 바꿔주세요.에디터를 다시 빌드하시거나, 라이브 코딩을 실행하시면 이제 보이실 겁니다.
블루프린트 복제하기
자 이제 기본적인 내용은 모두 살펴보았으니 제대로 된 기능을 만들어보자구요 !
이번에 만들어볼 기능은 블루프린트 복제하기 입니다.
네? 이건 그냥 컨트롤 C+V 하면 되는거 아니냐구요? 맞아요. 하지만 저희는 프로그래머이기 때문에 반복적인걸 싫어하고 귀찮음이 맥스인 사람들이라 최대한 빠르고 쉽게 끝내고 싶잖아요?
만약 복사해야되는게 30개, 50개 100개이면 어우… 또 이 기능을 베이스로 안의 내용물을 랜덤하게 바꿔서 복제하기 등 다양하게 활용할 수 있겠죠?
에셋에 대하여 어떠한 특정 작업을 하기 위해서 아래 두 라이브러리의 도움을 받을 수 있어요.
이 두 라이브러리는 앞으로도 많이 쓰일 예정이니 한번씩 살펴보는 걸 추천해요.
UEditorUtilityLibraryUEditorAssetLibrary
최종코드
void UQuickAssetAction::DuplicateAssets(int32 NumOfAssets)
{
if (NumOfAssets <= 0)
{
return;
}
TArray<FAssetData> SelectedAssetData = UEditorUtilityLibrary::GetSelectedAssetData();
uint32 Counter = 0;
for (const FAssetData& AssetData : SelectedAssetData)
{
for (int i = 0; i < NumOfAssets; ++i)
{
const FString SourceAssetPath = AssetData.GetObjectPathString();
const FString NewDuplicateAssetName = AssetData.AssetName.ToString() + TEXT("_") + FString::FromInt(i + 1);
const FString NewPathName = FPaths::Combine(AssetData.PackagePath.ToString(), NewDuplicateAssetName);
if(UEditorAssetLibrary::DuplicateAsset(SourceAssetPath, NewPathName))
{
UEditorAssetLibrary::SaveAsset(NewPathName, false);
++Counter;
}
}
}
if (Counter > 0)
{
Print(FString::FromInt(Counter) + TEXT("개의 파일이 복제되었습니다."), FColor::Green);
}
}
- 선택된 에셋의 데이터 배열을 가져옵니다.
- 각 에셋 데이터의 경로와 새롭게 생성될 에셋의 이름을 설정하고 최종 경로를 지정합니다.
- 에셋 복제를 실행하고 새롭게 만든 에셋을 저장합니다.
3) 예시


마무리
매번 지루하고 반복적인 작업을 어떻게하면 줄일 수 있을까를 고민하면서 에디터에 나만의 기능을 추가하고 싶다는 생각을 하곤 했습니다.
그 첫번째로 블루프린트 복제하기를 해보았는데요, 첫 글로 조금은 부족하지 않았을까라는 생각도 하게 됩니다. 그래도 막상 구현하고 나니 뿌듯하네요.
다들 자신만의 언리얼 엔진을 만들어 보시면 좋겠습니다. 그럼 다음 게시글에서 뵙겠습니다.
