Unreal 공부

[Unreal] Custom Anim Node 만들기

겨울꿈개발자 2021. 10. 17. 00:25

현재 Unreal을 시작한지 약 2주일 정도 된것 같습니다.

Unity를 추석동안 잠깐 만져보다가 Unreal을 배우면 많은 공부가 될 것 같아서 본격적으로 진행해보고자 합니다.

 

목표는 간단한 3D 게임을 만들어보는 것입니다.

해당 게임에다가 여러가지 기능들을 덕지덕지 붙이면 하나의 게임이 나올 것 같네요.

 

추후에는 자체적인 캐릭터 모델을 사용해야겠지만 현재는 흥미를 붙일 겸 원신이라고 하는 게임의 아야카 캐릭터 모델을 사용하고 있습니다.

해당 게임 개발사 미호요에서는 게임 캐릭터 모델을 pmx 형식으로 제공하고 있습니다. 물론 상업적인 이용은 안되지만 개인 프로젝트 사용에는 문제가 없을 것으로 보입니다. 무슨 이유인지는 모르겠지만 아야카 캐릭터는 기존에 올라왔다가 지금은 내려갔습니다. 다행히 인터넷에서 검색을 조금 하면 찾을 수 있습니다.

 

pmx 모델은 MMD 영상을 만들때 많이 사용하는 모델로 보입니다.

해당 형식의 모델은 Unreal에서 사용할 수 없기 때문에 blender 등의 디자인 프로그램을 통해 fbx 파일로 바꾸는 작업이 필요합니다. blender도 pmx 형식의 파일을 바로 사용못하기 때문에 해당 파일을 받아들이는 플러그인을 찾아서 사용해야 합니다. 인터넷 검색을 통해 관련 플러그인을 사용했었습니다.

 

기회가 되면 pmx 모델을 fbx 모델로 변환하고 이를 Unreal에 올리는 작업도 포스팅해봐야겠네요.


현재까지 진행된 상황은 다음과 같습니다.

아래 그림은 Unreal의 애니메이션 블루프린트 기능을 이용하여 아야카 모델의 대기/걷기 상태를 구현한 그림입니다.

대기/걷기 애니메이션은 Unreal에서 제공하는 3d 캐릭터 조작하는 샘플 프로젝트의 애니메이션을 사용하였습니다.

해당 애니메이션을 아야카 모델에 적용하기 위해 리타기팅 작업도 진행하였습니다.

 

큰 문제는 샘플 애니메이션은 아야카 모델에 있는 치마, 머리카락의 움직임을 제어하고 있지 않기 때문에

그대로 사용할 경우에 다리가 치마를 뚫고 나오는 현상이 발생합니다.

이를 처리하기 위해 Kawaii Physics라고 하는 Unreal 플러그인을 사용하였습니다.

해당 플러그인은 애니메이션 블루프린트에서 사용할 수 있는 노드를 제공하며,

단순히 아래 그림과 같이 애니메이션을 해당 노드와 연결하고 노드의 파라메터를 적절히 조작하면,

다리가 올라감에 따라 치마도 같이 올라가는 효과를 적용할 수 있습니다.

해당 노드의 캡슐 충돌체 파라메터가 많은 도움이 됐습니다.

 

아래 블루프린트 구조를 좀더 설명드리자면 현재로써는 크게 3가지로 나뉘어집니다.

1. 대기 애니메이션에 Kawaii Physics를 적용하여 치마/머리카락의 움직임 추가 (아래 블루프린트의 11시 지역)

2. 걷기 애니메이션에 Kawaii Physics를 적용하여 치마/머리카락의 움직임 추가 (아래 블루프린트의 5시 지역)

3. 대기/걷기/뛰기 애니메이션에 대해서 주어진 Speed 변수 값에 따라 블렌딩하여 최종 애니메이션 출력 (아래 블루프린트의 3시 지역)

현재까지 진행된 원신 아야카 모델의 대기/걷기/뛰기 애니메이션 처리 블루프린트


문제는 뛰기 애니메이션 처리 과정중에 발생합니다.

아래는 뛰기 애니메이션에 Kawaii Physics 플러그인 처리 결과를 보여줍니다.

오른쪽 다리가 현재 치마를 뚫고 나왔으며, 치마의 뼈가 오른쪽 다리에 맞게 같이 올라가지 못하고 옆으로 흘러 내리기에 발생하는 문제입니다.

이에 대해서 드는 생각은 옆으로 흘러 내려가지 못하게 관련 움직임을 제한했으면 하지만, 아직 Unreal에 익숙치 않아서 관련 기능을 찾지 못했습니다. Kawaii Physics에서도 관련 파라메터를 못 찾았습니다.

 

달리기 모션에 대해서 잘 처리가 되지 않는 모습

따라서 이를 처리해주는 노드를 만들어보고자 합니다.

 

우선 이에 앞서 Custom Anim Node를 만들어본적이 없기에 관련 자료들을 찾아봤습니다.

 

1. C++을 이용한 블루프린트 함수 노드 만들기

  • 가장 간단한 강좌이며, 이벤트 그래프 내에서 사용할 수 있는 함수 노드를 만드는 강좌입니다.
  • 다만 Animation 블루프린트에서는 사용을 못하는 것으로 보입니다.
  • https://www.youtube.com/watch?v=Wxa5SS5H2CM
Unreal에서 C++을 이용하여 이벤트 그래프에서 사용할 수 있는 함수 node 만드는 영상

2. Unreal 공식 문서 - 애니메이션 노드 테크니컬 가이드

 

애니메이션 노드 테크니컬 가이드

애님 블루프린트의 그래프 안에서 사용할 노드를 새로 만드는 방법에 대한 안내서입니다.

docs.unrealengine.com

3. 직접 애니메이션 노드를 만드는 방법을 설명한 영상

Unreal C++로 Custom Anim Node 만드는 영상 - 1
Unreal C++로 Custom Anim Node 만드는 영상 - 2
Unreal C++로 Custom Anim Node 만드는 영상 - 3

위에서 3번째에 해당하는 영상에 대한 내용들을 필기한 부분이 이번 글의 주 내용입니다.

해당 영상은 총 1시간짜리 영상이며, 해당 영상은 Unreal 플러그인도 만들어보면서 플러그인 구성 요소도 어느 정도 파악을 할 수 있습니다.

 

해당 영상에서는 UBIKSolver라고 하는 플러그인을 만드는 과정을 보여줍니다.

 

더보기

§ Part 1

    □ 해당 강좌에서는 자체적으로 가지고 있는 UBIKSolver 라고 하는 소스 코드를 사용하나, 해당 코드를 가지고 있지 않은 관계로 그냥 진행함.

    1) UE4 에디터에서 '기본' 타입의 새로운 플러그인을 생성한다. (이름: UBIKSolver)

        a) 생성한 플러그인은 파일 탐색기에서 Plugin 폴더에서 확인할 수 있다.

        b) 기존 UE4 규칙에 맞게 하기 위해 해당 플러그인 폴더 내 Source 폴더 내에 있는 UBIKSolver 폴더의 이름을 UBIKEditor, UBIKRuntime으로 각각 바꾸었다.

        c) 바꾼 UBIKEditor 폴더 내 아래 파일들의 이름을 수정

            i) UBIKSolver.Build.cs -> UBIKEditor.Build.cs

            ii) Public/UBIKSolver.h -> Public/UBIKEditor.h

            iii) Private/UBIKSolver.cpp -> Private/UBIKEditor.cpp

        d) UBIKRuntime 폴더도 UBIKEditor 폴더에서 수정한 바와 같이 해당 파일들의 이름들을 수정한다.

    2) 에픽게임즈 런처의 라이브러리 탭에서 현재 사용중인 엔진 버전의 옵션에서 '엔진 소스' 부분을 활성화한다.

        ® '디버깅을 위한 편집기 기호' 도 UE4 디버깅을 위해 필요한 옵션으로 보이나 용량이 꽤 크니 설치에 주의해야 함.

    3) 이후 Visual Studio 편집기에서 코드 분석 진행

        ® 솔루션 폴더 내 Engine 폴더에서 UE4 엔진 코드를 확인할 수 있음.

        ® 그 중에서 Source 폴더 내에 Editor, Runtime 폴더가 있는데 이 부분이 블루 프린트와 연관이 있는 것으로 보임.

            ◊ Editor - 실제 UE4 에디터에 표시되는 내용을 다룸.

            ◊ Runtime - 실제 노드의 실행 기능을 다룸.

        ® Editor 폴더 내에 AnimGraph 폴더가 있으며, 해당 폴더가 UE4 에디터 내 AnimGraph 창에서 사용하는 블루프린터 노드 관련 내용을 확인할 수 있음.

            ◊ 그 중에서 Classes 폴더 내 AnimGraphNode_ModifyBone.h 파일이 있으며, 해당 파일 내에서 사용하는 속성 FAnimNode_ModifyBone 구조체는 Runtime 폴더 내 AnimNode_ModifyBone 이름의 h, cpp 에서 정의하고 있다. 

            ◊ 여기서 AnimGraph.Build.cs 파일에서 관련 빌드 의존성 정보를 확인할 수 있다.

                } 그 중에서 PublicDependencyModuleNames 에 속하는 AnimGraphRuntime, BlueprintGraph 항목을 앞에서 생성한 UBIKSolver 플러그인 내 Editor 폴더의 UBIKEditor.Build.cs 파일 내에 추가한다.

                } 또한 PrivateDependencyModuleNames 에 속하는 GraphEditor, PropertyEditor, EditorStyle 항목도 위에 추가한 파일에다가 추가한다.

                } 해당 파일 내 UBIKSolver 클래스 이름을 UBIKEditor로 수정한다. 

                } UBIKRuntime.Build.cs 파일에도 클래스 이름은 UBIKRuntime 으로 수정한다.

    4) UBIKSolver 플러그인 폴더 내 UBIKSolver.uplugin 파일 내용 내에 있는 Modules 배열 정보를 수정한다.

        a) 기존에는 UBIKSolver 이름의 모듈 요소가 하나 있는데, 해당 모듈 이름은 UBIKEditor, UBIKRuntime 으로 각각 수정한다.

    5) 지금까지 파일 탐색기를 통해 변경한 내용을 반영하기 위해 기존 열려있는 Visual Studio 에디터를 닫고 현재 사용중인 UE4 프로젝트 최상위 폴더에 있는 "프로젝트명".uproject 확장자 파일 우클릭 > "Generate Visual Studio Project files" 클릭한다. 이후 같은 위치에 있는 Visual Studio 솔루션을 통해 에디터를 다시 열면 변경한 내용들이 잘 적용되어있음을 확인할 수 있다.

    6) UBIKSolver 플러그인 코드 수정 작업 진행

        a) UBIKEditor.h 내 클래스 명 FUBIKEditor 로 적용

        b) UBIKEditor.cpp 내 내용 수정

            i) #include "UBIKEditor.h" 로 수정

            ii) #define LOCTEXT_NAMESPACE "UBIKEditor" 로 수정

            iii) StartupModule, ShutdownModule 함수의 클래스 명 FUBIKEditor로 수정

            iv) IMPLEMENT_MODULE(FUBIKEditor, UBIKEditor)

        c) UBIKRuntime.h 및 cpp 도 위와 같은 내용 적용

    7) 이후 솔루션 빌드 진행

    8) 이후 UE4 에디터의 C++ 클래스 생성시에 UBIKRuntime 및 UBIKEditor를 타입으로 지정할 수 있음을 확인할 수 있다.

    

§ Part 2

    1) UE4 에디터에서 C++ 클래스 생성 (이름은 AnimNode_UBIKSolver, 타입은 UBIKRuntime (Runtime))

    2) 기존 엔진 코드를 참고하여 새로 만든 클래스 내용 수정

        a) AnimNode_UBIKSolver.h

            i) AnimNode_ModifyBone.h 의 앞 부분 (#include 파트까지) 을 복사해서 추가

                One. 이후 BoneController/AnimNode_SkeletonControlBase.h 및 AnimNode_ModifyBone.generated.h 만 남긴다.

                Two. #include "AnimNode_ModifyBone.generated.h" -> #include "AnimNode_UBIKSolver.generated.h"

            ii) 다시 참고한 헤더 파일에서 FAnimNode_SkeletalControlBase 함수 정의 부분을 복사해서 추가

                One. UBIKRUNTIME_API, FAnimNode_UBIKSolver 이름으로 변경

                Two. 기존에 있던 생성자, 소멸자는 제거

                Three. 결과적으로 해당 함수의 몸체에는 GENERATED_USTRUCT_BODY() 만 남아있다.

            iii) 참고한 헤더 파일에서 public virtual 함수들을 복사해서 추가

                One. IsValidToEvaluate 함수는 제거

            iv) 추가한 virtual 함수들에 대해 Visual Studio 의 "빠른 작업 및 리팩토링" 기능을 이용하여 정의 추가 -> cpp 파일에 관련 함수들의 몸체가 생성된다.

        b) AnimNode_UBIKSolver.cpp 파일 내에 생성자와 소멸자 정의 부분은 삭제

        c) 빌드 시 에러가 생기며, 이를 해결하기 위해 UBIKRuntime.Build.cs 파일의 PublicDependencyModuleNames에 "AnimGraphRuntime" 요소 추가

        

§ Part 3

    1) UE4 에디터에서 C++ 클래스 생성 (이름은 AnimGraphNode_UBIKSolver, 타입은 UBIKEditor (Runtime))

    2) 기존 엔진 코드를 참고하여 새로 만든 클래스 수정

        a) AnimGraphNode_UBIKSolver.h

            i) AnimGraphNode_ModifyBone.h 의 앞 부분 (#include 파트까지) 을 복사해서 추가

                One. AnimGraphNode_SkeletonControlBase.h 를 남기고, AnimGraphNode_UBIKSolver.generated.h 추가

            ii) 참고한 헤더 파일에서 UAnimGraphNode_UBIKSolver 클래스 앞 부분 (public 함수 선언 부분까지) 복사해서 추가

                One. Part2에서 진행한 바와 같이 몇가지 이름들 변경 및 생성자/소멸자 제거

                Two. UPROPERTY 변수의 타입을 FAnimNode_UBIKSolver 타입으로 변경

        b) AnimGraphNode_UBIKSolver.cpp

            i) 기존 내용 다 지우기

            ii) 앞에서 수정한 헤더 파일 내 함수들에 대한 몸체 자동 생성 (Visual Studio 빠른 작업 및 리팩토링 기능 이용)

            iii) AnimGraphNode_ModifyBone.cpp 파일 맨 위와 아래 부분의 LOCTEXT_NAMESPACE 매크로의 #define, #undef 를 복사에서 추가

            iv) 앞에서 자동 생성한 함수들의 몸체는 LOCTEXT() 매크로를 리턴하도록 수정, 해당 매크로 내 인자 2개는 적절한 값으로 채워넣기

    3) 빌드시 생기는 오류들을 해결하기 위해 아래 작업들을 수행함

        a) UBIKEditor.Build.cs 파일에서 PublicDependecyModuleNames에 추가한 AnimGraphRuntime 및 BluePrintGraph는 PrivateDependencyModulesNames에 추가하고, UBIKRuntime을 PublicDependencyModuleNames에 추가, AnimGraph를 PrivateDependencyModuleNames에 추가

        b) AnimGrpahNode_UBIKSolver.h 에 #include "AnimNode_UBIKSolver.h" 추가

        c) AnimGraphNode_UBIKSolver.h 파일 내 클래스 안의 GENERATED_BODY() 로 대체 (이미 상위 클래스가 GENERATED_UCLSS ? 부분을 가지고 있기 때문이라고 영상에서 설명)

    4) 이후 빌드는 되는데, UE4 에디터의 애님그래프에서 UBIK_Solver 노드를 불러오려고 하면 에러가 발생함. (Pure virtual not implemented)

    5) 해당 문제를 수정하기 위해 아래 작업들을 수행함

        a) AnimGraphNode_ModifyBone.h 파일 내 FAnimNode_SkeletalControlBase* GetNode() 함수 선언 부분을 복사해서 AnimGraphNode_UBIKSolver.h 에 추가


아래와 같이 애님 그래프에서 UBIK Solver라고 하는 노드를 불러올 수 있음을 확인할 수 있습니다.

해당 노드의 기능을 C++로 작성하면 애니메이션 포즈도 수정할 수 있을 것으로 기대하고 있습니다.

강좌 따라하면서 만들어본 UBIK Solver 노드

우선 Kawaii Physics 플러그인 코드를 어느정도 분석해보면서 원하는 기능을 구현해볼 수 있을지 확인해봐야겠습니다.