애니메이션 블루프린트인 이유
"애니메이션 블루프린트"가 그냥 "블루프린트" 보다 친숙하게 들립니다. 물론 블루프린트가 재미는 있었지만, 이제 애니메이션 블루프린트와 블루프린트는 다른 방식으로 작동하는 것 같으니, 여기서 짚어보고자 합니다.
먼저, 언리얼 엔진에서의 애니메이션 재생 방식에 대해 이야기해 봅시다.
스켈레탈 메시 컴포넌트에 애니메이션을 재생하는 방식은 두 가지 있습니다. 이미 잘 아시듯이 스켈레탈 메시 컴포넌트에는 본 계층구조가 들어있고, 거기에는 애니메이션을 재생할 수 있는 스키닝된 메시가 포함됩니다. 애니메이션을 레벨에 끌어놓으면, 스켈레탈 메시 컴포넌트가 포함된 스켈레탈 메시 액터가 생성되고, 기본적인 정보가 약간 셋업되어 나옵니다.
디테일 패널에서 액터를 선택할 때는 데이터의 이 부분을 특히 주의깊게 보세요.
모든 스켈레탈 메시 컴포넌트에는 애니메이션 모드 세팅이 있으며, 여기서 앞서 말씀드린 애니메이션 재생 방식 둘 중 하나를 설정합니다.
- Use Animation Asset: 애니메이션 애셋 사용 - 애님 시퀀스와 애님 컴포짓에만 적용됩니다. 주어진 타임라인상에 유효한 포즈를 낼 수 있는 애셋 하나입니다.
- Use Animation Blueprint: 애니메이션 블루프린트 사용 - 애니메이션 블루프린트를 재생할 수 있는 모드입니다.
첫 번째 옵션은 단순합니다만, 두 번째 옵션은 설명이 필요합니다.
두 번째 옵션은 Use Animation Blueprint, 애니메이션 블루프린트 사용 입니다.
콘텐츠 브라우저에서 애님 블루프린트를 끌어 레벨 뷰포트에 놓으면, 아래처럼 애님 블루프린트가 셋업된 스켈레탈 메시 액터가 생성됩니다 (위의 애님 시퀀스를 레벨 뷰포트에 끌어놓는 동작과 비슷합니다).
애니메이션 하나 재생은 단순하지만, 복수의 애니메이션 재생 및 각기 다른 조건에 따라 서로를 블렌딩하는 다양한 블렌딩 애니메이션 재생은 조금 더 복잡한데, 바로 거기에 애니메이션 블루프린트가 쓰입니다. 파라미터나 현재 시간과 같은 현재 상태에 따라 작동합니다.
애니메이션 블루프린트를 생성하면 두 개의 그래프가 보이는데, 다음 링크에 자세히 설명되어 있습니다.
https://docs.unrealengine.com/latest/KOR/Engine/Animation/AnimBlueprints/index.html
그래프가 이벤트 그래프와 애님 그래프, 두 개 있습니다.
이벤트 그래프는 애님 인스턴스에 대해서 블루프린트와 같습니다. 변수를 설정하고 함수를 호출할 수 있으며, 거기에는 발동되는 이벤트가 있습니다. 각 노드를 호출하여 실행시키키는 액션 시퀀스도 있습니다.
애님 그래프는 약간 다릅니다. 애니메이션이 블렌딩되는 곳이지요. 액션 시퀀스라기 보다는 트리 구조에 가깝습니다. 각 노드마다 있는 별도의 처리 단계를 통해 포즈를 생성합니다.
그러면 이벤트 그래프 예제를 먼저 살펴봅시다.
블루프린트를 아시는 분들은 아주 쉽게 이해하실 수 있습니다. 애니메이션을 업데이트하는 이벤트가 발동되면 Speed (속력)을 설정하고 방향을 계산한 다음 Direction (방향)을 설정합니다.
그러면 애님 그래프는 어떻게 작동할까요? 방식이 약간 다릅니다.
위 그림은 걷기 애니메이션 재생이 최종 애니메이션 포즈로 갑니다. 실행 순서는 여전히 왼쪽에서 오른쪽이며, 각 노드는 일회성이라기 보다는 지속되는 상태에 가깝습니다. 현재는 반복되는 애니메이션 하나 뿐입니다. 다음 단계로 나아가기 위해서 각 노드는 휘발성 데이터를 저장해야 합니다. 그래서 스테이트, 상태가 등장합니다.
[0,1] 범위 실수 값에 따라 두 개의 애니메이션을 블렌딩하고플 때는 어떻게 할까요?
애니메이션 시스템 업데이트시 다음과 같은 순서로 처리됩니다:
- 이벤트 그래프 업데이트
- 애님 그래프 업데이트
- 트리거 이벤트
이벤트 그래프를 먼저 업데이트하는 이유는 모든 변수가 업데이트되도록 하여, 애님 그래프에서는 그 변수를 사용하여 블렌딩을 올바르게 처리합니다.
본 트랜스폼은 아무것도 바꾸지 않습니다. 시간 변화에 따른 사물의 "상태"를 업데이트하는 것이 전부입니다. 그러면 언제 본 트랜스폼을 바꾸고 프레임에 맞는 포즈를 생성할까요? 그것은 Evaluate 에서 일어납니다.
애님 그래프에는 세 가지 이벤트가 생깁니다.
- Initialize, 초기화
- Update, 업데이트
- Evaluate, 계산
이벤트 그래프에는 Evaluate 가 필요치 않아 이벤트가 둘 뿐입니다.
- 초기화
- 업데이트
보통 초기화는 한 번이지만, 메시를 바꿔 "재초기화" 가 필요한 경우, 다시 발생할 수 있습니다.
Update 와 Evaluate 는 모든 틱마다 발생합니다. Evaluate 는 유효 포즈 결과를 내는 녀석입니다. 이렇게 분리하는 이유는? 거의 최적화 때문입니다. Evaluate 는 트랜스폼에 엄청난 양의 수학 연산을 하는 애니메이션 프로세스 중 가장 비싼 부분인데, 게임과의 상호작용이 필요치 않으므로 쉽게 병렬처리 가능합니다. 반면 Update 에는 종종 블루프린트 함수 호출을 뜻하는 애님 노티파이와 같은 "트리거 이벤트"가 있습니다. 이는 게임 내 다른 부분과의 상호작용이 필요하므로, 병렬 처리하기가 매우 어렵습니다.
본 트랜스폼 변경에 대해서는 어떤가요? 그 작업은 어디서 해야 할까요?
대부분의 이 작업을 블루프린트에서 하고싶어 하는 것 같습니다. 블루프린트에서 하는 것이 편할 수는 있겠지만, 제 생각에는 애니메이션 블루프린트에서 하는 것이 더욱 적합한 것 같습니다.
애니메이션 블루프린트는 모든 본 트랜스폼을 계산하여 최종 결과를 내는 곳입니다. 이 작업을 한 곳에서 할 수 있으면 좋을텐데, 블루프린트에서 해 버리면 틱 순서에 따라 최신의 본 트랜스폼 정보를 얻지 못할 수가 있습니다. 이런 상황을 가정해 봅시다:
- 프레임 시작
- ….
- 블루프린트가 본 트랜스폼 업데이트
- 애니메이션 블루프린트 호출됨 - 모든 본 트랜스폼 업데이트
- ….
- 프레임 끝
이렇게 되면 애니메이션 블루프린트는 변경 여부를 신경쓰지 않기에 기존 변경내용을 잃게 됩니다. 그래프를 실행시키고, 그에 맞게 트랜스폼을 업데이트하는 것이지요. 순서를 바꾼다면 정상 작동할 것입니다.
- 프레임 시작
- ….
- 애니메이션 블루프린트 호출됨 - 모든 본 트랜스폼 업데이트
- 블루프린트가 본 트랜스폼 업데이트
- ….
- 프레임 끝
그런데 이제 다른 블루프린트에서도 변경을 가하려 한다고 칩시다. 그러면 일이 매우 복잡해 집니다.
본 트랜스폼 연산을 집중시키는 가장 좋은 방법은, 하나의 인스턴스에 하나밖에 없는 애니메이션 블루프린트에서 일어나도록 하는 것입니다. Transform Node 를 사용하여 본 트랜스폼을 변경하세요.
변경하고자 하는 트랜스폼 컴포넌트와 스페이스까지도 설정할 수 있습니다.
애니메이션 블루프린트는 매우 강력한 툴입니다. 레이어드 블렌딩, 애디티브 애니메이션 블렌딩, 변수를 통한 블렌딩, 스테이트, 트랜지션 등 많은 노드가 제공됩니다. 저희가 제공하는 ContentExample 프로젝트의 Animation.umap 에서 직접 확인해 보실 수도 있습니다.
자세히 알아보려면 다음 링크를 참고해 주세요. 어떤 피드백이든 환영합니다.
https://docs.unrealengine.com/latest/KOR/Engine/Animation/AnimBlueprints/index.html