최근 간단한 상호 작용 시스템을 언리얼에서 구현해야했습니다. (자세한 내용은 현재 개발 중인 게임이라 회사 기밀...) 여하튼 상호 작용이 일어나면 물리적인 상태 변화가 일어나야했고 동적인 물리까지 쓸 일은 아니었으므로 애니메이션을 베이킹해서 플레이하는 방식으로 진행되었습니다.
언리얼에서 애니메이션을 구현하는 방법은 다양하게 있습니다. 언리얼5의 물리 시스템인 카오스를 사용할 수도 있고, 스켈레탈 메쉬를 사용할 수도 있습니다. 저는 그 중에서도 가장 성능 면에서 가벼운 버텍스 애니메이션(Vertex Animation)을 사용했습니다.
버텍스 애니메이션은 버텍스들의 위치 정보를 프레임 단위로 최대 8K 텍스쳐에 저장하여 World Position Offset으로 애니메이션을 구현하는 방식입니다. 텍스쳐의 X축에는 버텍스의 인덱스 수만큼 위치 정보가, Y축에는 프레임의 수만큼 위치 정보가 저장되며, 따라서 최대 8192개의 버텍스를 8192 프레임만큼 애니메이팅 할 수 있습니다.
Vertex Animation Tools 스크립트는 언리얼 엔진 디렉토리 내에 있습니다. 아래 경로를 참고하세요! (경로는 언리얼 엔진을 설치한 위치에 따라 다를 수 있으나 Engine 폴더 아래로는 동일합니다)
C:\Program Files\Epic Games\(엔진 버전)\Engine\Extras\3dsMaxScripts\VertexAnimationTools.ms
사실 버텍스 애니메이션 사용법은 언리얼 공식 문서에 너무 자세하게 나와 있어 많은 설명이 필요없습니다. 아래 두 문서와 유튜브에 있는 튜토리얼 동영상을 차례로 참고하시면 됩니다.
언리얼 엔진 | 버텍스 애니메이션 툴
언리얼 엔진 | 버텍스 애니메이션 툴 - 타임라인 메시
UE4 - Tutorial - Vertex Animation (3DS Max to Unreal Material)
간단히 순서를 요약하면 아래와 같습니다.
3ds Max에서 원하는 애니메이션을 구현합니다. 위에 소개한 튜토리얼처럼 간단히 Morpher 모디파이어를 사용해서 구현할 수도 있고, 저의 경우 3ds Max 내의 MassFX 애니메이션 툴을 사용해 물리 기반 애니메이션을 구현하였습니다.
3ds Max Tutorial - MassFX Basics
Vertex Animation Tools라는 스크립트를 3ds Max 뷰포트에 드래그 앤 드랍해서 실행한 후 버텍스 애니메이션으로 변환하고자 하는 애니메이션이 포함된 오브젝트들을 전부 클릭해서 Process Animated Meshes를 클립합니다.
2의 과정이 끝나면 2개의 텍스쳐를 저장할 위치를 지정하라는 창이 뜹니다. 적절한 곳에 저장하세요. 그리고 3ds Max 아웃라이너를 보면 "_MorphExport" 라는 접미사가 붙은 오브젝트가 생성됩니다. 버텍스 애니메이션을 재생시키기 위해 버텍스 인덱스가 알맞게 설정된 단일 오브젝트입니다. 마찬가지로 동일한 경로로 FBX 익스포트 해줍니다.
언리얼 엔진으로 넘어갑니다. [언리얼 엔진 | 버텍스 애니메이션 툴 - 타임라인 메시]의 설명에 따라 위에서 저장한 텍스쳐 파일 2개와 FBX 파일 하나를 임포트하고 기본 설정값들을 변경해줍니다. 머테리얼 구성법도 자세히 나와있으니 참고하시길 바랍니다.
제가 버텍스 애니메이션을 활용하면서 궁금했던 점들에 대해 정리해두겠습니다.
1. 3ds Max에서 다수의 오브젝트가 일련의 애니메이션을 구성할 경우 어떻게 해야하나?
예컨대, 벽돌을 수십개 쌓아서 만든 벽을 무너뜨리는 애니메이션을 만들었다면 모든 벽돌 오브젝트를 선택한 후 버텍스 애니메이션으로 변환하시면 됩니다. 이 경우, 벽돌들이 모두 포함된 하나의 버텍스 애니메이션 전용 오브젝트가 생성되며, 그 오브젝트와 사용할 수 있는 텍스쳐 파일 2개가 생성됩니다.
2. 복잡한 애니메이션도 깔끔하게 재생되나요?
꽤나 복잡한 애니메이션도 양질의 결과를 보여주었습니다. 다만 버텍스의 개수와 프레임의 수가 최대 8192개를 넘어갈 수 없으며 버텍스의 위치가 오브젝트의 원점에서 멀어질수록 정밀도가 떨어진다고 합니다.
3. 버텍스 애니메이션으로 변환하는데 걸리는 시간은?
애니메이션의 복잡도에 따라 생각보다 오래걸리기도 합니다. 버텍스의 수가 많을수록, 프레임의 수가 많을수록 더욱 오래걸립니다. 컴퓨터 성능에 따라 다르겠지만 64GB RAM / RTX3070 기준 별도의 특별한 작업을 하지 않으면서 8000개의 버텍스를 150 프레임만큼 버텍스 애니메이션으로 변환하는 데에 애니메이션의 복잡도에 따라 15분에서 많게는 40분 정도 걸렸습니다.
4. 성능은 어느 정도인가요?
머테리얼에서 재생하는 애니메이션이기에 상당히 가벼웠습니다. 버텍스 애니메이션 기본 세팅에 프레임 조절용 스칼라 파라미터 2개, 에셋의 베이스 컬러용 텍스쳐 한 개, AO/Roughness/Metallic 텍스쳐 한 개, 노말 텍스쳐 한 개를 포함한 머테리얼이 SM5 기준 Pixel Shader 145 인스트럭션, Vertex Shader 253 인스트럭션을 사용합니다.
5. 모바일에서 사용 가능한가요?
가장 우려되는 점이었으나 안드로이드의 경우 Galaxy Note 8과 Galaxy S10 5G에서 모두 재생되었으며 준수한 성능을 보여주었습니다.
6. 기존 마스터 머테리얼에 적용 가능한가요?
버텍스 애니메이션은 전용 노말맵을 생성합니다. 이 노말맵은 월드 스페이스 노말맵이며 탄젠트 스페이스 노말맵으로 변환하지 않고 그대로 사용하도록 공식 문서와 관련 머테리얼 함수에서 권장합니다. 하지만 저는 탄젠트 스페이스로 변환해서 원래 애셋의 노말맵과 'BlendAngleCorrectedNormals'로 블랜딩하여 사용했고 큰 문제는 없었습니다.
7. LOD 설정이 가능한가요?
버텍스 정보를 토대로 애니메이션이 구현되기 때문에 버텍스 정보가 임의로 변경되는 LOD 설정이 불가능합니다. 따라서 거리에 따른 최적화를 원한다면 LOD 단계별 버텍스 애니메이션 텍스쳐와 메쉬를 따로 제작해야합니다. 하지만 그만큼 메모리를 사용하게 되겠죠.
8. 마주했던 문제점은?
무슨 이유에서인지 3DMax에서 버텍스 애니메이션 텍스쳐와 메쉬를 생성할 경우 스무딩 그룹이 전부 사라졌습니다. 이게 문제인 이유는 버텍스 애니메이션용 노말맵은 버텍스마다 노말 정보를 저장하는데, 버텍스가 너무 적거나 고르게 분포되지 않은 경우 노말이 예쁘게 나오지 않습니다. 따라서 버텍스 수를 최적화하는 것에 한계가 있습니다.