프로그래밍/unreal engine

[UE]나만의 Animation node 만들기1

민냐옹 2022. 9. 3. 12:26

언리얼 엔진에서 custom anim node를 플러그인 방식으로 만들어보자.
UE 에디터의 뷰포트 툴바 아이콘 중 Settings > plugins > new plugin > 공백(Blank)를 선택한다. 내가 만드는 플러그인의 Name이나 Author, Description 같은 항목은 마음대로 쓰자.

나는 플러그인 이름을 PluginTest로 지었다. 이대로 생성하면 프로젝트 폴더에 Plugins라는 폴더가 추가 생성되고 이 폴더 안에 내가 PluginTest 폴더가 들어가 있다.

앞으로 이 PluginTest 폴더 안에 내가 만든 애니메이션 노드를 구성하는 2개의 클래스(정확히는 하나의 클래스와 하나의 구조체)를 만들어 집어넣을 거다.

왜 2개의 클래스가 필요한가? 공식 문서와 공식 안내서에도 잘 나와있지만 애니메이션 노드는 두 클래스, 정확히는 두 부분으로 나눠져있기 때문이다. 
하나는 UE 에디터에서 내 애니메이션 노드를 보이게 하는 애님 그래프 노드(Anim Graph Node) 즉 UAnimGraphNode_Base 파생 클래스다. 나머지는 실제 런타임에서 사용될 애님 비헤이비어 노드(Anim Behavior Node)인 FAnimNode_Base 파생 구조체다.

애님 그래프 노드는 애니메이션 노드의 이름과 색상, 툴팁 표시 등 에디터 관련 작업을 하고 애님 비헤이비어 노드는 블렌딩과 타겟 위치 계산, 올바른 최종 포즈 반환 등 실제 작업을 한다. 그래서 애님 그래프 노드는 에디터에서, 애님 비헤이비어 노드는 런타임에서 중요하게 작용한다.

모든 애님 그래프 노드는 연관된 애님 비헤이비어 노드를 멤버변수로 갖는다. 마치 애니메이션 블루프린트의 AnimGraph상에 배치되서 내 눈에 보이는 애니메이션 노드가 자기 내부에 실제 작업을 담당하는 기능을 멤버변수로 품고 있는 형태다.

이런 구조상 애님 그래프 노드는 애님 비헤이비어 노드에 대해서 알고 있지만, 반대 방향은 성립하지 않는다.(공식 안내서에서는 이게 굉장히 중요한 차이라고 설명한다. 이런 구조 때문에 애님 그래프 노드 클래스의 .Build.cs 파일의 PublicDependencyModuleNames에는 애님 비헤이비어 노드의 모듈이 들어가지만 반대는 성립되지 않는 모양이다. 이게 뭔 말인지는 아래에서 다시 설명한다.) 모든 애님 그래프 노드는 이런 이유 때문에 에디터 모듈에 존재하는 거고, 게임과 함께 로드되지는 않고 에디터에서만 존재한다.

개념은 간단히 훑었고 다시 만드는 과정을 살펴보자.
앞서 설명했듯이 에디터 작업을 하는 클래스와 런타임 작업을 하는 클래스를 만들어야 한다. 수월한 진행을 위해 이미 UE에서 제공하는 애니메이션 노드 중 TransformModifyBone를 예시로 쓰자.

내 프로젝트의 sln파일을 열고 솔루션 탐색기에서 UE > Source > Editor >AnimGraph > Classes > AnimGraphNode_ModifyBone.h을 열어보자. 

위 이미지처럼 UAnimGraphNode_ModifyBone 클래스가 UAnimGraphNode_SkeletalControlBase를 상속한다고 나와있다. UAnimGraphNode_SkeletalControlBase가 UAnimGraphNode_Base를 상속하기 때문에 TransformModifyBone의 애님그래프 노드 클래스는 UAnimGraphNode_Base 파생 클래스라는 걸 확인할 수 있다.

위 이미지를 잘 보면 멤버변수로 FAnimNode_ModifyBone Node가 포함돼있는 게 보인다.  이 멤버변수가 바로 런타임에서 실제 작업을 담당하는 애님 비헤이비어 노드다.

 

TransformModifyBone의 애님 비헤이비어 노드 클래스는 UE > Source > Runtime >AnimGraphRuntime >Public > BoneControllers > AnimNode_ModifyBone.h에서 찾을 수 있다.

FAnimNode_ModifyBone 구조체는 FAnimNode_SkeletalControlBase를 상속하고 있다는데 당연히 FAnimNode_SkeletalControlBase는 FAnimNode_Base를 상속하고 있다.

 

내 PluginTest도 이런 구조를 갖춰야 한다. 현재 내 PluginTest > Source 폴더 안에는 PluginTest 폴더가 존재할 텐데 이 폴더 이름을 PluginTestRuntime으로 바꾸자. 얘는 애님 비헤이비어 노드 클래스를 담당시킬 거다.

PluginTestRuntime폴더의 복사본을 만들고 얘 이름은 PluginTestEditor로 바꾸자. 얘는 애님 그래프 노드 역할을 맡을 거다.

 

PluginTestEditor 폴더부터 작업해보자. 이 내부에 Build.cs 파일(일부러 구체적으로 파일 이름을 명시 안 했다. 이유는 아래로 내려보면 안다.)이 있는데 이 파일 내부에 모듈을 추가해줘야 한다. 
TransformModifyBone의 애님 그래프 노드를 위한 AnimGraph.Build.cs 파일을 열어보면 내 것에 추가할 모듈 BlueprintGraph, GraphEditor, PropertyEditor, EditorStyle 등이 보인다. 

AnimGraph.Build.cs 파일

PublicDependencyModuleNames의 모듈 중에 AnimGraphRuntime는 TransformModifyBone의 애님 그래프 노드가 알고 있어야 하는 애님 비헤이비어 노드에 대한 모듈이다.
위에서 애님 그래프 노드는 애님 비헤이비어 노드에 대해서 알고 있다고 한 걸 여기서 확인할 수 있다. 애님 그래프 노드 역할의 클래스에서 애님 비헤이비어 노드 역할의 구조체를 멤버변수로 들고 있으려니 이렇게 모듈을 추가하고 있는 거다.

내가 만든 PluginTestEditor는 당연히 TransformModifyBone의 AnimGraphRuntime모듈을 알 필요가 없으니 이걸 제외한 다른 필요한 모듈들만 아래 이미지처럼 추가한다.

아래 이미지의 PluginTestRuntime는 PluginTestEditor가 알고 있어야 하는 애님 비헤이비어 노드 관련 모듈이라서 추가한 거다.

PluginTestEditor.Build.cs 파일

참고로 현재 수정 중인 내 Build.cs 파일 이름은 PluginTestEditor.Build.cs가 아니고 이 파일 내부의 클래스 이름도 PluginTestEditor로 안 돼있을 거다. 처음 PluginTestEditor 폴더를 만들 때 원본이 되는 폴더 이름 PluginTest을 그대로 쓰고 있을 거다. 이 PluginTest 이름을 다 PluginTestEditor로 바꿔줘야 한다. PluginTestEditor 폴더 내부의 h, cpp 파일 이름(물론 파일 내부의 클래스 이름들도 다 변경해야 한다.)도 다 PluginTestEditor로 바꿔줘야 한다.

PluginTestEditor.h 파일 내부의 클래스 이름을 PluginTestEditor에 맞게 변경했다.
PluginTestEditor.cpp 파일 내부의 클래스, 모듈 이름들도 바꿔주자.

이 이름 바꿔주는 작업은 당연히 PluginTestRuntime 폴더에서도 해줘야 한다. PluginTest폴더로 경로를 이동해 이 폴더에 있는 PluginTest.uplugin 파일 내부에서도 PluginTestEditor, PluginTestRuntime 모듈 추가 겸 이름 작업을 해줘야 한다.

PluginTest.uplugin 파일

이대로 컴파일 후 빌드가 잘 되는지 확인해보자. PluginTestEditor, PluginTestRuntime 이름으로 바꿔야 할 부분을 실수로 놓치면 컴파일 에러가 뜨니 꼼꼼하게 확인해봐야 한다.

빌드 완료 후 현재 작업 중인 UE 프로젝트를 열고 새 c++ 클래스를 만들어보려 하면 아래 이미지처럼 내가 만든 PluginTestEditor, PluginTestRuntime 폴더 경로가 잘 뜬다.

 

다음 작업은 이후 글에서 다루겠다. 이 작업은 UE 4.27 버전으로 진행했다.

'프로그래밍 > unreal engine' 카테고리의 다른 글

[UE]나만의 Animation node 만들기2  (1) 2022.09.10