언리얼 엔진 에서 애니메이션 블루프린트를 사용하여 애니메이션 시스템을 개발할 때, 여러 가지 애니메이션 최적화 기법을 사용하여 프로젝트 퍼포먼스를 개선할 수 있습니다.
이후 문서에서는 언리얼 엔진에서 애니메이션 시스템을 최적화하는 기법의 모범 사례 몇 가지를 자세히 알아볼 수 있습니다.
개요
프로젝트의 애니메이션 시스템 퍼포먼스, 또는 각 프레임의 평가 효율성은 게임 스레드(Game Thread) 및 작업자 스레드(Worker Threads) 에서 틱(Tick) 마다 애니메이션 시스템 처리에 필요한 시간을 기반으로 합니다.
애니메이션은 애니메이션 블루프린트에 추가되어 런타임 시 캐릭터에 대해 평가되고 재생됩니다. 애니메이션 블렌딩, IK 평가, 피직스 시뮬레이션 등의 추가 프로세스는 각각 평가를 위해 프로젝트 퍼포먼스 버짓을 차감합니다. 간단해서 평가를 위한 퍼포먼스 버짓이 별로 필요 없는 프로세스도 있지만, 더 고급 연산을 수행하여 더 멋진 비주얼의 애니메이션을 생성하지만, 그에 따라 많은 퍼포먼스 버짓이 필요한 프로세스도 있습니다. 모든 애니메이션 시스템 기능에는 퍼포먼스 비용이 결부되어 있습니다.
일반적으로, 애니메이션 블루프린트에서 퍼포먼스 비용이 가장 많이 소모되는 연산은 이벤트 그래프(Event Graph) 로직입니다. AnimGraph 로직은 빠른 경로 같은 시스템을 사용하여 최적화할 수 있지만, 최고의 퍼포먼스를 달성하기 위해서는 이벤트 그래프 로직을 최대한 줄이는 것이 좋습니다. 이벤트 그래프는 틱마다 평가되며, 각 프로세스는 게임 스레드 에서 순차적으로 발생합니다.
아래의 다이어그램은 단일 애니메이션 프레임을 개념적으로 분석한 것입니다. 각 애니메이션 프레임에는 여러 개의 틱이 포함되어 있으며, 틱마다 이벤트 그래프가 평가됩니다. 이벤트 그래프 평가는 일반적으로 각 틱에서 수행되는 가장 큰 연산입니다. 이벤트 그래프 평가는 순차적으로 처리되므로 각 틱의 평가를 완료하는 데는 시간이 더 걸립니다.

사용할 수 있는 작업자 스레드 에서 동시에 평가할 수 있는 Thread Safe 함수 에 이벤트 그래프 로직을 재배치하여 이 프로세스를 최적화할 수 있습니다.
아래의 다이어그램에서 각 틱 완료 시간이 극적으로 감소한 것을 볼 수 있습니다. 모든 이벤트 그래프 연산을 Thread Safe 함수에 재배치하면, 연산을 동시에 수행할 수 있으므로 각 틱 평가에 필요한 시간이 상당히 감소하고 애니메이션 시간 퍼포먼스가 개선됩니다.

멀티 스레드 애니메이션 업데이트 사용하기
애니메이션 블루프린트 이벤트 그래프는 항상 게임 스레드 에서 실행됩니다. 멀티 스레드를 활용하기 위해 이벤트 그래프 내의 로직을 최적화하려면, Thread Safe 함수 를 사용하여 로직을 빌드하면 됩니다.
스레드 안정성을 보장하려면 변수처럼 프로젝트 내의 다른 블루프린트 및 컴포넌트에서 파생된 데이터에 대한 모든 레퍼런스를 애니메이션 블루프린트로 푸시하는 것이 아니라 애니메이션 블루프린트를 통해 호출해야 합니다.
Blueprint Thread Safe Update Animation
Blueprint Thread Safe Update Animation 오버라이드 함수를 사용하여 스레드 세이프 방식으로 애니메이션 블루프린트의 로직을 평가할 수 있습니다. 내 블루프린트(My Blueprint) 패널의 함수(Function) 섹션 옆에 있는 오버라이드(Override) 드롭다운 메뉴에서 Blueprint Thread Safe Update Animation 함수를 선택하여 애니메이션 블루프린트에 추가할 수 있습니다.

Thread Safe 함수
Thread Safe 함수는 블루프린트 함수로서, 이 함수를 사용하여 애니메이션 시스템이 사용할 수 있는 변수와 프로퍼티를 설정하는 로직을 수행할 수 있으며, 이벤트 그래프에서 일반적으로 수행되는 다른 연산도 수행할 수 있습니다.
애니메이션 블루프린트에서 Thread Safe 함수를 생성하려면 내 블루프린트 패널에서 + 추가(+ Add) 버튼을 사용하여 새 함수를 생성합니다. 그런 다음, 새 함수의 디테일(Details) 패널을 열고 스레드 세이프(Thread Safe) 프로퍼티를 활성화합니다.

그러면 스레드 세이프가 활성화된 함수를 Blueprint Thread Safe Update Animation 오버라이드 함수에 추가하여 틱마다 작업자 스레드를 사용할 수 있을 때 동시에 평가할 수 있습니다.

프로퍼티 액세스
Thread Safe 함수는 스레드 세이프가 아닌 블루프린트와 컴포넌트에 바로 액세스할 수 없습니다. 스레드 세이프가 아닌 블루프린트와 해당 프로퍼티에 안전하게 액세스하려면, 프로퍼티 액세스(Property Access) 기능을 사용하여 블루프린트의 데이터를 읽고 함수를 호출하면 됩니다. 프로퍼티 액세스는 Thread Safe 함수의 그래프 내에서, 또는 AnimGraph 노드에 있는 핀의 프로퍼티 내에서 독립형 노드로 사용될 수 있습니다.


Property Access 노드 | Property Access 핀
Property Access 노드를 생성하려면, Thread Safe 함수의 그래프에서 우클릭하고 컨텍스트 메뉴에서 프로퍼티 액세스(Property Access) 옵션을 선택합니다.

Property Access 노드를 사용하여 자신의 애니메이션 블루프린트와 관련된 다른 블루프린트 및 오브젝트에 있는 변수와 컴포넌트 및 데이터를 참조할 수 있습니다. 프로퍼티 액세스 데이터 호출의 소스를 정의하려면, 바인드(Bind) 드롭다운 메뉴를 선택한 다음, 참조하려는 컴포넌트나 프로퍼티를 선택합니다. 프로퍼티나 컴포넌트를 선택하여 오브젝트나 데이터를 바로 참조할 수도 있고, 프로퍼티나 컴포넌트의 중첩된 옵션을 탐색하여 해당 컴포넌트나 프로퍼티에 바로 액세스할 수도 있습니다.

이제 바인딩된 프로퍼티 액세스 레퍼런스를 사용하여 Thread Safe 블루프린트 함수 내에 추가 프로퍼티나 변수를 설정할 수 있습니다.

Thread Safe 함수 및 프로퍼티 액세스 데이터 사용에 대한 자세한 내용은 애니메이션 블루프린트에서 그래프 사용하기 문서를 참조하세요.
Thread Safe 함수 및 프로퍼티 Property Access 사용하여 애니메이션 변수를 가져오는 워크플로 예시는 애니메이션 변수를 가져오는 방법 문서를 참조하세요.
스레드 세이프 함수를 사용하기 위해 언리얼 엔진 프로젝트를 최적화하는 워크플로 예시는 UE5 게임에 라이라 애니메이션 응용하기 블로그 게시물을 참조하세요.
애니메이션 빠른 경로
애니메이션 빠른 경로(Animation Fast Path) 를 사용하면 AnimGraph 업데이트 내에서 변수 액세스를 최적화할 수 있습니다. 이를 통해 엔진은 블루프린트 가상 머신(Blueprint Virtual Machine) 호출하게 되는 블루프린트 코드를 실행하는 대신 내부적으로 파라미터를 복사할 수 있습니다. 이 컴파일러는 현재 다음과 같은 구조체를 최적화할 수 있습니다.
-
멤버 변수(Member Variables)
-
음의 부울 멤버 변수(Negated Boolean Member Variables)
-
중첩된 구조체의 멤버(Members of a Nested Structure)
애니메이션 빠른 경로를 사용하려면, 블루프린트의 AnimGraph 내에서 실행 중인 블루프린트 로직이 없어야 합니다.
다음 예시 블루프린트에서 AnimGraph는 여러 블렌드 스페이스(Blend Space) 에셋과 Blend 노드를 구동하여 Output Pose 를 생성하는 데 사용되고 있는 몇 개의 float 값을 읽고 있습니다. 오른쪽 상단 코너에 번개 아이콘이 있는 각 노드는 실행 중인 로직이 없으므로 빠른 경로를 사용하고 있습니다.

그래프에 어떤 형태의 계산이든 추가되면, 관련된 노드는 더 이상 빠른 경로를 사용하지 않게 됩니다. 다음 예시에서는 간단한 float 변수에 단순한 곱하기 함수가 추가되어 해당 Blend Space 노드가 빠른 경로를 사용할 수 없게 됩니다. 그래프가 컴파일된 다음에는 번개 아이콘이 제거되어 이러한 변화를 나타냅니다.

빠른 경로 메서드
다음은 애니메이션 블루프린트에서 빠른 경로 변수 액세스 구현에 사용할 수 있는 메서드입니다.
멤버 변수 직접 액세스
빠른 경로를 사용하여 변숫값에 직접 액세스하고 읽어 출력 포즈를 결정할 수 있습니다.

중첩된 구조체의 멤버 액세스
로테이터 변수 같은 중첩된 구조체를 분해하여 해당 컴포넌트에 직접 액세스하면서도 빠른 경로를 계속 사용할 수 있습니다. 그래프에서 해당 변수를 우클릭하고 컨텍스트 메뉴에서 구조체 핀 분할(Split Struct Pin) 을 선택하거나 Break 노드를 사용하여 구조체를 바로 분해할 수 있습니다. 이제 구조체의 컴포넌트 값에 바로 액세스할 수 있습니다.

Break Transform 같은 일부 Break Struct 노드는 단순히 데이터를 복사하는 것이 아니라 내부적으로 변환을 수행하므로 빠른 경로를 사용하지 않습니다.
블루프린트 사용 경고
애니메이션 블루프린트가 빠른 경로를 사용하는지 확인하려면 블루프린트 사용 경고(Warn About Blueprint Usage) 프로퍼티를 활성화하면 됩니다. 블루프린트 사용 경고가 활성화된 경우, 컴파일러는 AnimGraph에서 블루프린트 가상 머신을 호출할 때 컴파일러 결과(Compiler Results) 패널에 경고를 표시합니다.
블루프린트 사용 경고 를 활성화하려면 애니메이션 블루프린트(Animation Blueprint) 의 클래스 세팅(Class Settings) 내 최적화(Optimization) 아래에서 해당 옵션을 활성화하면 됩니다.

블루프린트 사용 경고 프로퍼티가 활성화된 상태로 AnimGraph에서 블루프린트 로직을 실행하면, 빠른 경로를 사용하여 액세스할 수 있는 변수가 아닌 경우 컴파일러 결과 패널에 경고 메시지가 표시됩니다. 경고 메시지의 링크를 클릭하면 그래프의 포커스가 경고 소스에 맞춰집니다. 이러한 기능은 최적화해야 할 사항을 트래킹하는 데 도움이 되며 최적화할 수 있는 노드 변수 액세스를 식별할 수 있게 해 줍니다.

애니메이션 최적화 툴
언리얼 엔진에서는 애니메이션 시스템을 분석하여 최적화할 부분을 찾는 데 사용할 수 있는 디버깅 툴세트를 제공합니다.
리와인드 디버거
리와인드 디버거(Rewind Debugger)를 사용하여 에디터에서 플레이 (Play in Editor, PIE) 시뮬레이션의 세그먼트를 녹화해 실시간으로 애니메이션 시스템을 분석할 수 있습니다. 트레이스(Traces) 를 사용하면 애니메이션 시스템 프로퍼티의 평가를 관찰하여 최적화할 수 있는 버그 및 퍼포먼스 문제를 파악할 수 있습니다.

리와인드 디버거 설정 및 사용법에 대한 자세한 내용은 아래의 문서를 참조하세요.
일반 팁
프로젝트의 애니메이션 시스템 퍼포먼스를 고려하기 시작할 때, 최적화 프로세스 중에 다음 가이드라인을 고려할 수 있습니다. 프로젝트마다 고유한 최적화 요구 사항이 있고 프로젝트의 규모와 범위에 따라 더 많은 변경이 필요할 수도 있지만, 다음 가이드라인은 대부분의 프로젝트에서 유용할 수 있는 일반적인 접근법을 제공합니다.
-
병렬 업데이트(Parallel Updates) 조건이 충족되었는지 확인합니다.
- UAnimInstance::NeedsImmediateUpdate 구조체에서 게임 스레드 에서 실행되는 애니메이션의 업데이트 단계를 피하기 위해 충족해야 하는 모든 조건을 확인할 수 있습니다. 캐릭터 무브먼트를 위해 루트 모션 이 필요한 경우, 캐릭터 무브먼트는 멀티 스레드가 아니므로 병렬 업데이트를 수행할 수 없습니다.
-
가능한 경우 업데이트 속도 최적화(Update Rate Optimizations, URO) 를 사용합니다.
-
URO는 애니메이션이 너무 자주 틱되지 않도록 합니다. URO 적용 방법은 프로젝트의 필요에 따라 다르지만, 대부분의 캐릭터에 대해 적절한 거리에서 15Hz 이하로 수행되는 업데이트 속도를 목표로 하고 보간을 비활성화하는 것이 좋습니다.
-
URO를 활성화하려면 스켈레탈 메시 컴포넌트의 디테일(Details) 패널에 있는 최적화(Optimization) 섹션으로 이동한 다음 업데이트 속도 최적화 활성화(Enable Update Rate Optimizations) 프로퍼티를 선택합니다. 그런 다음,
AnimUpdateRateTick()
구조체를 사용하여 블루프린트 틱 속도를 설정하고 관찰하면 됩니다.
-

- 필요에 따라, 스켈레탈 메시 컴포넌트 디테일 패널에서 디스플레이 디버그 업데이트 속도 최적화(Display Debug Update Rate Optimizations) 프로퍼티를 활성화하여 시뮬레이션 중 프로젝트에 적용되는 URO 속도의 디버그 디스플레이를 화면에 표시할 수도 있습니다.

URO를 사용하는 대신 Animation Budget Allocator 플러그인을 사용하여 애니메이션 블루프린트 평가의 틱 속도를 제어하는 것이 좋습니다.
-
캐릭터가 피직스 에셋에 액세스할 필요가 없다면, 컴포넌트 고정 스켈레탈 바운드 사용(Component Use Fixed Skel Bounds) 을 활성화합니다.
- 스켈레탈 메시 컴포넌트의 디테일 패널에서 컴포넌트 고정 스켈레탈 바운드 사용 프로퍼티를 활성화합니다.
-
그러면 피직스 에셋 사용을 건너뛰고 대신 스켈레탈 메시에 정의된 고정 바운드를 항상 사용하게 됩니다.
-
또한, 프레임마다 컬링을 위한 바운딩 볼륨 재계산을 건너뛰므로 퍼포먼스도 향상됩니다.
기타 고려 사항
애니메이션 인사이트를 사용하여 프로젝트를 프로파일링하는 경우, 작업자 스레드 프로세스를 완료한 뒤에 메인 스레드에서 스켈레탈 메시에 대해 FParallelAnimationCompletionTask가 실행되는 것을 볼 수도 있습니다. 이 프로세스는 병렬 업데이트 조건이 충족되면 프로파일에 표시되는 메인 스레드 작업의 대부분을 차지합니다. 이는 일반적으로 설정에 따라 다음과 같은 몇 가지 작업으로 구성됩니다.
-
피직스 오브젝트 업데이트 같은 프로젝트 컴포넌트의 무브먼트 계산
- 가능한 경우 실제로 필요하지 않은 항목의 피직스는 업데이트는 하지 않도록 합니다. 이렇게 하면 FParallelAnimationCompletionTask가 가장 많이 감소합니다.
-
애니메이션 노티파이 개시
-
모든 노티파이는 블루프린트 가상 머신을 호출하지 않기 위해 블루프린트 기반이 아니어야 합니다.
-
노티파이는 애니메이팅된 오브젝트의 수명에 영향을 줄 수 있으므로 게임 스레드 에서 수행되어야 합니다.
-
-
URO가 활성화된 경우 애니메이션의 보간
-
머티리얼 또는 모프 타깃 커브가 사용 중인 경우 커브 블렌딩