인터체인지 프레임워크(Interchange Framework) 는 언리얼 엔진의 임포트 및 익스포트 프레임워크입니다. 파일 포맷에 구애받지 않으며, 비동기식이고, 커스터마이징할 수 있으며, 런타임 시 사용할 수 있습니다.
인터체인지 임포트 인터페이스
인터체인지는 확장할 수 있는 코드 베이스를 사용하며 커스터마이징할 수 있는 파이프라인 스택을 제공합니다. 그렇기 때문에 프로젝트의 특성에 맞춰 블루프린트나 Python을 사용하여 임포트 파이프라인을 자유롭게 편집할 수 있습니다.
중요 개념 및 용어
- 파이프라인(Pipeline) : 임포트된 데이터를 처리하는 작업 컬렉션입니다. 파이프라인은 임포트 프로세스를 커스터마이징할 때 사용하는 옵션을 보여줍니다.
- 파이프라인 스택(Pipeline Stack) : 임포트된 파일을 처리하는 파이프라인을 정렬한 목록입니다. 파이프라인은 스택에서 결합되며 특정 파일 포맷에 할당됩니다. 파이프라인 스택은 프로젝트 세팅(Project Setting) > 인터체인지(Interchange) 에 있습니다.
- 팩토리(Factory) : 임포트된 데이터에서 에셋을 생성하는 작업입니다.
인터체인지 플러그인 활성화
인터체인지 프레임워크에는 Interchange Editor 및 Interchange Framework 플러그인이 필요하며, 두 플러그인은 기본적으로 활성화되어 있습니다. 프로젝트에 두 플러그인이 활성화되어 있지 않다면, 프로젝트의 프로젝트 세팅에서 활성화할 수 있습니다. 플러그인 활성화에 대한 자세한 내용은 플러그인으로 작업하기를 참조하세요.
에셋 임포트하기
에셋은 여러 가지 방법을 통해 언리얼 엔진에 임포트됩니다. 에셋을 임포트하려면 콘텐츠 드로어(Content Drawer)나 콘텐츠 브라우저(Content Browser)를 사용할 수도 있고, 파일(File) > 레벨로 임포트(Import Into Level) 를 선택할 수도 있습니다. 파일 임포트에 대한 자세한 내용은 에셋을 직접 임포트하기를 참조하세요.
현재 레벨로 임포트 는 glTF 및 MaterialX 파일 포맷으로 가능합니다.
임포트 프로세스
다음은 임포트 프로세스를 트리거하는 방법입니다.
- 위에 나열된 방법 중 하나를 사용하여 임포트 프로세스를 시작합니다.
- 그러면 인터체인지 파이프라인(Interchange Pipeline) 환경설정 창이 열립니다.
- 파이프라인 스택 선택(Choose Pipeline Stack) 드롭다운 메뉴에서 사용할 파이프라인 스택을 선택합니다.
- 세팅을 환경설정하고 임포트(Import) 를 눌러 프로세스를 완료합니다.
인터페이스를 사용하여 임포트 세팅을 선택하고 임포트를 클릭하여 계속 진행합니다.
어느 방법을 사용하든 엔진은 인터체인지 프레임워크에서 해당 파일 포맷을 지원하는지 확인합니다. 지원하는 경우 인터체인지는 포맷에 맞는 임포트 파이프라인 스택을 사용해서 다음 프로세스를 진행합니다.
- 인터체인지는 임포트된 데이터를 언리얼 엔진에서 중간 노드 구조체로 변환합니다.
- 인터체인지는 파이프라인 스택을 통해 이동하며 임포트 지침을 따릅니다.
- 팩토리를 사용하여 결과에서 에셋을 생성합니다.
인터체인지에서 해당 파일 포맷을 지원하지 않으면, 언리얼 엔진은 레거시 프레임워크를 사용하여 파일을 임포트합니다.
인터체인지를 사용하여 에셋 리임포트하기
전에 인터체인지를 사용하여 임포트한 에셋을 리임포트하는 경우, 언리얼 엔진은 전에 사용한 파이프라인 스택과 옵션을 기억한 후 해당 옵션을 표시합니다.
블루프린트를 사용하여 에셋 임포트하기
블루프린트를 사용하면 인터체인지 프레임워크를 통해 언리얼 엔진에 에셋을 임포트할 수 있습니다.
이 블루프린트 예시는 런타임 시 인터체인지를 사용하여 파일을 임포트하는 오브젝트를 생성합니다.
예를 들어 이 기능을 사용하면 언리얼 엔진 기반의 애플리케이션에서 런타임 시 인터체인지를 통해 파일을 임포트할 수 있습니다. 위의 예시는 디폴트 텍스처 파이프라인 스택을 사용하여 지정된 파일 위치에 텍스처 파일을 임포트하는 함수를 생성합니다. 이 임포트 방식은 현재 스켈레탈 메시나 애니메이션 데이터를 지원하지 않습니다.
새 블루프린트 클래스 생성하기
예시를 재현하는 절차는 다음과 같습니다.
- 해당 함수를 포함할 새 액터 블루프린트 클래스를 프로젝트에 생성합니다. 콘텐츠 브라우저(Content Browser) 에서 우클릭하고 컨텍스트 메뉴에서 블루프린트 클래스(Blueprint Class) 를 선택합니다.
-
부모 클래스 선택(Pick Parent Class) 창에서 액터(Actor) 를 선택하고 새 블루프린트 클래스 이름을 InterchangeActor 로 지정합니다.
새 블루프린트의 부모 클래스를 선택합니다.
함수 추가하기
- 새 블루프린트를 더블클릭하여 에디터를 엽니다.
-
내 블루프린트(My Blueprint) 패널의 함수(Functions) 섹션에서 + 버튼을 클릭하고 새 함수 이름을 InterchangeImport 로 지정합니다.
새 함수 생성
노드 추가 및 연결하기
- Sequence 노드를 추가하고 함수의 출력에 연결합니다.
- Then 0 출력에서 드래그하고 임포트될 기존 파일을 참조하는 Create Source Data 노드를 생성합니다.
- Create Source Data 의 In File Name 입력에서 드래그하고 컨텍스트 메뉴에서 변수로 승격(Promote to Variable) 을 선택합니다.
- 새 스트링 변수 이름을 FilePath 로 지정합니다. 이 변수에는 임포트될 파일의 위치가 저장되어 있습니다.
- 블루프린트에서 새 변수를 선택하고 인스턴스 편집가능(Instance Editable) 체크박스를 선택합니다. 그러면 변수를 블루프린트의 인스턴스별로 편집할 수 있습니다.
- Create Source Data 노드의 출력을 SourceData 라는 새 변수로 승격합니다.
- Sequence의 Then 1 출력에서 드래그하고 Get Interchange Manager Scripted 노드를 생성합니다. 그러면 다음 단계에서 사용할 인터체인지 매니저(Interchange Manager)의 포인터가 생성됩니다.
- Get Interchange Manager Scripted 출력에서 드래그하고 Import Asset 노드를 생성합니다. Get Interchange Manager Scripted 의 반환 값(Return Value)을 Import Asset 의 타깃(Target) 입력에 연결합니다.
- 콘텐츠 경로(Content Path) 입력에서 드래그하고 SavePath 라는 새 변수로 승격합니다. 이 변수에는 새로 임포트될 파일의 위치가 저장되어 있습니다.
- 블루프린트에서 새 변수를 선택하고 인스턴스 편집가능 체크박스를 선택합니다.
- 소스 데이터 변수에 대한 레퍼런스를 가져와 Import Asset 의 소스 데이터(Source Data) 입력에 연결합니다.
-
에셋 파라미터 임포트(Import Asset Parameters) 입력에서 드래그하고 Make Input Asset Parameters 노드를 생성합니다.
전체 크기로 보려면 이미지를 클릭하세요.
런타임 시 함수 사용 가능하게 만들기
- 내 블루프린트 패널에서 InterchangeImport 함수를 클릭하고 디테일(Details) 패널의 에디터에서 호출(Call In Editor) 옆의 체크박스를 선택합니다. 이 옵션을 활성화하면 InterchangeActor 오브젝트의 디테일 에서 런타임 시 이 함수를 사용할 수 있습니다.
- 블루프린트를 저장(Save) 하고 컴파일(Compile) 합니다.
새 블루프린트 사용하기
- InterchangeActor 블루프린트의 사본을 레벨에 드래그합니다.
- 재생(Play) 을 클릭합니다.
- 아웃라이너(Outliner) 에서 InterchangeActor 를 선택합니다.
- 디테일 패널에서 FilePath 및 SavePath 를 입력합니다.
- 인터체인지 임포트(Interchange Import) 버튼을 클릭하여 파일을 임포트합니다.
위의 블루프린트 예시와 함께 Import Scene 노드를 추가하면 에셋이 씬에 바로 스폰됩니다.
쿠킹된 애플리케이션에서 인터체인지 사용하기
쿠킹된 애플리케이션에서 런타임 시 인터체인지 프레임워크를 사용할 계획이라면, 프로젝트 세팅의 프로젝트(Project) - 패키징(Packaging) 섹션에서 쿠킹할 추가 에셋 디렉터리(Additional Asset Directories to Cook) 에 해당 Interchange 폴더를 추가합니다.
전체 크기로 보려면 이미지를 클릭하세요.
Python을 사용하여 에셋 임포트하기
Python 스크립트를 사용하여 인터체인지 프레임워크를 통해 언리얼 엔진에 에셋을 임포트할 수 있습니다.
import unreal
gltf_path = "D:/projectPS/gltf/sketchfab/ship_in_a_bottle/scene.gltf"
source_data = unreal.InterchangeManager.create_source_data(gltf_path)
import_asset_parameters = unreal.ImportAssetParameters()
import_asset_parameters.is_automated = True
eas = unreal.get_editor_subsystem(unreal.EditorAssetSubsystem)
import_asset_parameters.override_pipelines.append(eas.load_asset("/Interchange/Pipelines/DefaultSceneAssetsPipeline"))
import_asset_parameters.override_pipelines.append(eas.load_asset("/Interchange/Pipelines/DefaultSceneLevelPipeline"))
ic_mng = unreal.InterchangeManager.get_interchange_manager_scripted()
ic_mng.import_scene("/game/testinterchange/autopython/",source_data,import_asset_parameters)
위의 예시에서는 블루프린트 예시와 비슷한 프로세스를 사용하여 scene.gltf 파일을 임포트하는 데 Python 스크립트를 사용합니다.
파이프라인 스택 편집하기
인터체인지 프레임워크의 장점 중 하나는 에셋 데이터가 처리되는 프로세스의 커스터마이징 가능한 스택인 파이프라인 스택을 선택하고 커스터마이징할 수 있다는 것입니다. 디폴트 파이프라인 스택에 파이프라인을 추가하여 임포트 프로세스 도중에 동작을 추가할 수 있습니다.
언리얼 엔진에는 다음과 같은 디폴트 파이프라인이 포함됩니다.
- 디폴트 에셋 파이프라인(Default Assets Pipeline)
- 디폴트 머티리얼 파이프라인(Default Material Pipeline)
- 디폴트 텍스처 파이프라인(Default Texture Pipeline)
- 디폴트 씬 에셋 파이프라인(Default Scene Assets Pipeline)
- 디폴트 씬 레벨 파이프라인(Default Scene Level Pipeline)
- 디폴트 그래프 인스펙터 파이프라인(Default Graph Inspector Pipeline)
각 디폴트 파이프라인에는 해당 유형의 임포트에 가장 많이 사용되는 옵션이 있습니다. 프로젝트의 특성에 맞춰 이러한 파이프라인을 추가로 커스터마이징할 수 있습니다.
기존 파이프라인 편집하기
각 디폴트 파이프라인은 프로젝트와 팀의 특성에 맞춰 커스터마이징할 수 있습니다.
프로젝트의 임포트 옵션을 커스터마이징하는 방법은 다음과 같습니다.
- 프로젝트 세팅 에서 기존 파이프라인 스택을 추가하거나 제거하거나 재정렬합니다.
- 기본적으로 사용할 파이프라인을 변경합니다.
- 기존 디폴트 파이프라인을 수정합니다.
- 커스텀 파이프라인을 생성합니다.
프로젝트 세팅 편집하기
프로젝트 세팅 의 엔진(Engine) > 인터체인지(Interchange) 아래에서 파이프라인 스택을 찾을 수 있습니다.
프로젝트 세팅의 파이프라인 스택입니다.
파이프라인 스택에는 다음과 같은 디폴트 세팅이 있습니다.
- 콘텐츠 임포트(Import Content)
- 레벨로 임포트(Import Into Level)
- 에디터 인터페이스(Editor Interface)
- 제네릭(Generic)
- 에디터 일반 파이프라인 클래스(Editor Generic Pipeline Class)
콘텐츠 임포트(Import Content)
언리얼 엔진은 이러한 세팅을 사용하여 콘텐츠 드로어 또는 콘텐츠 브라우저 에 콘텐츠를 임포트합니다.
전체 크기로 보려면 이미지를 클릭하세요.
나열된 각 콘텐츠 타입의 세팅을 변경할 수 있습니다. 필요 시 헤딩을 더 추가할 수도 있습니다. 예를 들어, 디폴트 환경설정에는 에셋(Assets), 머티리얼(Materials), 텍스처(Textures) 가 포함되어 있습니다. 애니메이션에 대한 파이프라인 스택에 섹션을 추가한 다음, 들어오는 애니메이션 파일을 처리할 하나 이상의 커스텀 파이프라인을 추가할 수 있습니다.
레벨로 임포트
에디터 창 메인 메뉴의 파일 > 레벨로 임포트 옵션은 엔진에 콘텐츠를 임포트할 때 이러한 세팅을 사용합니다. 기본적으로 레벨로 임포트는 함께 작동하는 두 개의 파이프라인을 사용하여 파일에서 액터 데이터를 임포트한 다음, 레벨에 액터를 스폰합니다.
전체 크기로 보려면 이미지를 클릭하세요.
- DefaultSceneAssetPipeline 은 DefaultAssetPipeline과 같은 클래스를 기반으로 하며 씬 임포트용으로 고안되었습니다.
- DefaultSceneLevelPipeline 은 DefaultSceneAssetPipeline을 통해 데이터가 전달된 뒤, 월드에 액터를 생성합니다.
기존 디폴트 파이프라인 수정하기
디폴트 인터체인지 파이프라인의 프로퍼티를 수정하여 다음과 같은 내용을 변경할 수 있습니다.
- 디폴트 값
- 비저빌리티
- 읽기 전용 상태
인터체인지 파이프라인 디테일 패널입니다.
다음 절차에 따라 디폴트 인터체인지 파이프라인의 세팅을 변경할 수 있습니다.
- 콘텐츠 드로어나 콘텐츠 브라우저에서 디폴트 파이프라인을 찾아 더블클릭하여 엽니다. 파이프라인은 Engine > Plugins > Interchange Framework Content > Pipelines 폴더에 있습니다. Engine 폴더가 보이지 않는다면, 콘텐츠 드로어 또는 콘텐츠 브라우저 오른쪽 상단의 세팅(Settings) 을 클릭하고 엔진 콘텐츠 표시(Show Engine Content) 체크박스를 선택합니다.
- 다음 항목을 원하는 대로 편집합니다.
- 임포트 및 리임포트 프로세스 때의 비저빌리티.
- 디폴트 세팅.
- 임포트 프로세스 때 프로퍼티를 읽기 전용으로 할지 여부.
- 저장하고 창을 닫습니다.
커스텀 파이프라인 생성하기
임포트 프로세스를 더 커스터마이징하기 위해 블루프린트나 C++, Python을 사용하여 인터체인지 파이프라인을 생성할 수 있습니다.
블루프린트를 사용하여 커스텀 파이프라인 생성하기
블루프린트를 사용하여 인터체인지 파이프라인을 생성하는 절차는 다음과 같습니다.
InterchangePipelineBase를 부모 클래스로 선택합니다.
- 콘텐츠 드로어 또는 콘텐츠 브라우저 를 우클릭하고 블루프린트 클래스 생성(Create Blueprint Class) 을 선택합니다.
- 부모 클래스 선택 창에서 모든 클래스(All Classes) 카테고리를 펼치고 InterchangePipelineBase 를 부모 클래스로 선택합니다.
새 블루프린트를 더블클릭하여 블루프린트 에디터(Blueprint Editor) 를 엽니다. 블루프린트를 사용하여 생성한 커스텀 파이프라인에는 커스텀 동작을 추가하기 위해 오버라이드할 수 있는 다음과 같은 함수가 있습니다.
인터체인지 블루프린트 오버라이드 함수입니다.
오버라이드 함수 | 설명 |
---|---|
Scripted Can Execute on Any Thread | 인터체인지 매니저에 이 파이프라인이 비동기 모드로 실행될 수 있다고 알립니다. |
Scripted Execute Export Pipeline | 익스포트 프로세스 중에 실행됩니다(현재 작동하지 않는 기능). |
Scripted Execute Pipeline | 파일 변환 후에 실행됩니다. 에셋 생성에 필요한 팩토리를 만듭니다. |
Scripted Execute Post Factory Pipeline | 팩토리가 에셋을 만든 후 PostEditChange 함수가 호출되기 전에 실행됩니다. |
Scripted Execute Post Import Pipeline | 에셋이 완전히 임포트되고 PostEditChange 함수가 호출된 후에 실행됩니다. |
Scripted Set Reimport Source Index | 파이프라인을 실행하고 리임포트할 소스 인덱스를 파이프라인에 알립니다. 둘 이상의 소스를 보유할 수 있는 에셋을 리임포트할 때 이 함수를 사용합니다. 지오메트리용 소스 파일 하나와 스키닝 정보용 소스 파일 하나가 있는 스켈레탈 메시를 예로 들 수 있습니다. |
C++을 사용하여 커스텀 파이프라인 생성하기
C++을 사용하여 새 인터체인지 파이프라인을 생성하려면 다음 내용이 포함된 헤더 파일을 생성합니다.
#pragma once
#include "CoreMinimal.h"
#include "InterchangePipelineBase.h"
#include "InterchangeSourceData.h"
#include "Nodes/InterchangeBaseNodeContainer.h"
#include "InterchangeMyPipeline.generated.h"
UCLASS(BlueprintType)
class INTERCHANGEPIPELINES_API UInterchangeMyPipeline : public UInterchangePipelineBase
{
GENERATED_BODY()
protected:
virtual void ExecutePipeline(UInterchangeBaseNodeContainer* BaseNodeContainer, const TArray<UInterchangeSourceData*>& SourceDatas) override;
virtual bool CanExecuteOnAnyThread(EInterchangePipelineTask PipelineTask) override
{
return true;
}
};
그 다음에는 아래 내용이 포함된 소스 파일을 생성합니다.
#include "InterchangeMyPipeline.h"
void UInterchangeMyPipeline::ExecutePipeline(UInterchangeBaseNodeContainer* NodeContainer, const TArray<UInterchangeSourceData*>& InSourceDatas)
{
Super::ExecutePipeline(NodeContainer, InSourceDatas);
// 변환된 노드나 팩토리 노드에 필요한 로직을 넣으세요.
}
언리얼 엔진에서 C++로 작업하는 방법에 대한 자세한 내용은 C++로 프로그래밍을 참조하세요.
Python을 사용하여 커스텀 파이프라인 생성하기
Python 스크립트를 사용하여 새 인터체인지 파이프라인을 생성하려면, 새 Python 스크립트를 생성한 다음 그 스크립트를 프로젝트 세팅을 사용하여 스타트업 스크립트에 추가합니다. 언리얼 엔진에서 Python 스크립팅으로 작업하는 방법에 대한 자세한 내용은 Python을 사용한 언리얼 에디터 스크립팅을 참조하세요.
아래의 예시 스크립트에서는 Python 스크립트를 사용하여 기본 에셋 임포트 파이프라인을 생성합니다.
import unreal
@unreal.uclass()
class PythonPipelineTest(unreal.InterchangePythonPipelineBase):
import_static_meshes = unreal.uproperty(bool,meta=dict(Category="StaticMesh"))
import_skeletal_meshes = unreal.uproperty(bool,meta=dict(Category="SkeletalMesh"))
def cast(self, object_to_cast, object_class):
try:
return object_class.cast(object_to_cast)
except:
return None
def recursive_set_node_properties(self, base_node_container, node_unique_id):
node = base_node_container.get_node(node_unique_id)
# 스태틱 메시 팩토리 노드 활성화 상태 설정하기
static_mesh_node = self.cast(node, unreal.InterchangeStaticMeshFactoryNode)
if static_mesh_node:
static_mesh_node.set_enabled(self.import_static_meshes)
# 스켈레탈 메시 팩토리 노드 활성화 상태 설정하기
skeletal_mesh_node = self.cast(node, unreal.InterchangeSkeletalMeshFactoryNode)
if skeletal_mesh_node:
skeletal_mesh_node.set_enabled(self.import_static_meshes)
# 자손 반복작업하기
childrens = base_node_container.get_node_children_uids(node.get_unique_id())
for child_uid in childrens:
self.recursive_set_node_properties(base_node_container, child_uid)
@unreal.ufunction(override=True)
def scripted_execute_pipeline(self, base_node_container, SourceDatas):
root_nodes = base_node_container.get_roots()
for node_unique_id in root_nodes:
self.recursive_set_node_properties(base_node_container, node_unique_id)
return True