개인 프로젝트를 진행하던 중 애니메이션 구조에 대해서 확장적인 설계에 대해 고민하게 되었으며

UE5 프레임워크의 이해를 돕기 위한 샘플 게임 프로젝트로 설계된 학습 리소스 "Lyra Starter Game"의 구조를 학습하며

이를 기반으로 애니메이션을 설계 및 리팩토링을 하고자 합니다.

이번 포스팅에서는 개인 프로젝트의 확장적 구조 설계 및 오버헤드 관련 최적화와 관련되어 학습한 Lyra 프로젝트 내
애니메이션에 대해 알아보겠습니다.

 

※ Lyra는 GAS(GameAbilitySystem)를 사용하여 설계되어있으며, 진행중인 프로젝트에서는 GAS를 사용하지 않습니다.
이로인해 GAS 관련된 학습 내용은 해당 포스팅에서 최소한의 부분만 작성하였습니다.

 

Lyra Animation 구조

 

ABP_Mannequin_Base

ABP_Mannequin_Base

C++ 클래스 LyraAnimInstance를 기반으로 생성된 애니메이션 블루프린트입니다.

 

LyraAnimInstance.h

UCLASS(Config = Game)
class ULyraAnimInstance : public UAnimInstance
{
	GENERATED_BODY()

public:

	ULyraAnimInstance(const FObjectInitializer& ObjectInitializer);

	virtual void InitializeWithAbilitySystem(UAbilitySystemComponent* ASC);

protected:

#if WITH_EDITOR
	virtual EDataValidationResult IsDataValid(class FDataValidationContext& Context) const override;
#endif // WITH_EDITOR

	virtual void NativeInitializeAnimation() override;
	virtual void NativeUpdateAnimation(float DeltaSeconds) override;

protected:

	// Gameplay tags that can be mapped to blueprint variables. The variables will automatically update as the tags are added or removed.
	// These should be used instead of manually querying for the gameplay tags.
	UPROPERTY(EditDefaultsOnly, Category = "GameplayTags")
	FGameplayTagBlueprintPropertyMap GameplayTagPropertyMap;

	UPROPERTY(BlueprintReadOnly, Category = "Character State Data")
	float GroundDistance = -1.0f;
};
  • FDataValidationContext
    • 데이터 검증을 위한 구조체
    • #if WITH_EDITOR를 사용하여 에디터 레벨에서만 컴파일되게 제한, 유효성검사를 하여 런타임 내 최적화
    • 데이터 검증에 따른 결과를 EDataValidationResult를 사용하여 반환한다.
      (Data Validation Plugin / UObjectGlobal.h)
  • FGameplayTagBlueprintPropertyMap

 

 

 

ABP_Mannequin_Base - AnimGraph

해당 애니메이션 그래프는 애니메이션을 직접 참조하는것이 아닌, 몽타주 및 LinkedAnimation Layer의 진입점을 제공하여 UpperBody / Lower Body 포즈를 혼합하여 재생할 수 있게 도와줍니다.

예를들어, Weapon들은 필요한 Montage 및 애니메이션 레이어에 대한 참조를 보유하고 있으며, 해당 Weapon이 로드될
경우 그에 맞는 애니메이션이 같이 로드되도록 합니다.

 

 

Blueprint ThreadSafe Update Animation

Anim Graph 로직 - Multi Thread 전 / 후

Multi Thread 전

ABP에 추가된 Blend, IK, Physics Simulation 등과 같은 런타임환경에서 값 계산하여 재생되는 애니메이션들은 추가될수록 성능에 대한 부정적인 영향을 줄 수 있습니다. 

이벤트 그래프 로직은 NativeUpdateAnimation 함수에서 매 틱마다 계산되며 일반적으로 Tick마다 호출되는 작업 중 이벤트 그래프 로직이 가장 큰 비중을 차지하게 됩니다.

매 틱마다 호출되는 이벤트 그래프 계산에 대한 성능 최적화를 위해 Lyra에서는 멀티스레드를 사용한 퍼포먼스 최적화 작업을 수행합니다.

 

Multi Thread 후

최적의 퍼포먼스로 실행하기위해 이벤트 그래프 대신 멀티스레드 애니메이션을 사용하여 애니메이션 값을 계산합니다.

애니메이션 최적화를 위한 기법 중 하나이며, Thread Safe 함수를사용하여 동시에 작업을 수행하여 각 Tick마다 필요한 시간을 줄이며 애니메이션 시스템 성능을 향상시킬 수 있습니다.

Project Settings - General Settings - Anim Blueprints - Allow MultiThreaded Animation Update

상단 이미지의 설정을 활성화하여 사용 할 수 있습니다.

 

ABP_Mannequin_Base - BlueprintThreadSafeUpdateAnimation

스레드 세이프는 이벤트 그래프에서처럼 게임 객체의 데이터에 직접 액세스 할 수 없습니다.

멀티스레드 환경에서 다른 스레드가 동시에 실행되어 해당 데이터를 변경할 수 있기 때문입니다.

Blueprint Update Animation에서는 Property Access를 사용하여 데이터 안정성이 보장될 경우(Thrad Safe할 경우) 자동으로 복사합니다.

Lyra에서는 MovementComponent, Controller, Owner 등의 값들을 AnimInstance 내부 변수로 캐싱하는데 사용하고있습니다.

 

※Property Access : 게임 스레드에서 실행되는 컴포넌트 또는 변수를 엑세스 하는 방법.
애니메이션 시스템의 퍼포먼스를 높이는 방법 중 하나이며, 스레드 세이프와 호환되도록 변환하는 방식으로 작동한다.

 

Animation Graph

ABP_Mannequin_Base - AnimGraph - Locomotion State Machine

ABP_Base내에서 스테이트 머신을 사용한 상태를 정의하며 상태의 동작은 ItemAnimLayerBase 계층에서 처리됩니다. 

 

Locomotion SM - Idle

 

Base 애니메이션 블루프린트 내에서 노드가 업데이트가 될 경우 UpdateIdleState관련 함수가 호출되도록 매핑이 되어있습니다. 해당 함수는 Idle 스테이트 로코모션 노드의 Output Pose를 계산하는데 사용되는 로직을 볼 수 있습니다.

출력되는 애니메이션은 Anim_ItemAnimLayers 기반의 애님 블루프린트 및 애니메이션 블루프린트 링크
(Animation Blueprint Linking)에서 결정하며 애니메이션 블루프린트 일부를 재사용 할 수 있습니다.

Locomotion을 재사용하기위해서 해당 애니메이션 블루프린트에 접근할 수 있도록 하는 방식은 Sub Anim Instance을 사용합니다.

 

 

애니메이션 블루프린트 링크 (Animation Blueprint Linking)

서브 애님 인스턴스 방식을 확장한 구조입니다.

애니메이션 그래프의 서브섹션을 동적으로 전환 할 수 있도록 지원합니다.

링크된 레이어 애니메이션 블루프린트를 사용하여 애니메이션 블루프린트의 여러곳을 오버라이드하여 사용 할 수 있습니다.

Lyra에서는 플레이어가 들고 있는 무기에 따라 Locomotion SM의 애니메이션 에셋, 포즈가 동적으로 전환될 수 있습니다.

 

애니메이션 레이어 인터페이스 (Animation Layer Interface)

ABP에서 애니메이션을 오버라이드할 수 있는 곳을 지정하는 역할을 합니다.

애니메이션 간 연결을 상속구조없이 재사용할 수 있게 설계된 모듈형 애니메이션 구조입니다.

Lyra에서는 모든 WeaponType이 사용하는 Aim Offset의 Yaw,Pitch와 같은 공통적으로 필요한 함수 및 프로퍼티들을 설정하고있습니다.

 

※ Sub Anim Instance - https://dev.epicgames.com/documentation/ko-kr/unreal-engine/using-sub-anim-instances-in-unreal-engine?application_version=5.0

※ Animation Blueprint Linking - https://dev.epicgames.com/documentation/ko-kr/unreal-engine/using-animation-blueprint-linking-in-unreal-engine

 

ABP_ItemAnimLayerBase

ABP_ItemAnimLayersBase - FullBody_StartState (Animation Layer)

PropertyAccess를 사용하여 값이 업데이트 될 경우 또는, 바인딩된 경우 설정한 함수를 실행합니다.

해당 함수를 실행하여 현재 애니메이션이 어떤것을 출력해야할지 동적으로 계산합니다.

Lyra에서 Anim Node Function을 사용하여 관련성이 있을 경우(바인딩 된 경우) 재생할 애니메이션을 선택하며,

또다른 시퀀스에서는 애니메이션의 재생속도를 관리하고 있습니다.

 

ABP_LocomotionLayers(Pistol, Rifle,  Shoutgun, Unarmed...)

ABP_RifleAnimLayers - Detail

ABP_ItemAnimLayersBase를 상속받은 Locomotion 폴더 내 ABP의 설정된 애니메이션을 실행합니다.

 

 

구조 정리

ABP_Mannequin_Base

  • 캐릭터에 연결된 메인 ABP
  • 애니메이션 그래프 내 Locomotion State Machine, Linked Animation Layer를 사용한 애니메이션 Entry Point 제공
  • Blend Pose를 위한 FullBody -> Upper/Lower Body Split
  • 런타임 환경에서 최종 출력될 애니메이션에 대한 값 계산
    • 애니메이션의 전체적인 흐름 제어 및 레이어 라우팅 담당

Linked Anim Layer (ALI_ItemAnimLayers)

  • ABP_Base의 Linked Animation 함수 실행
  • ALI_ItemAnimLayers에 정의된 함수들이며, 상속구조없이 바인딩가능, 유연성 및 재사용성 증가

 

ABP_ItemAnimLayerBase

  • ALI_ItemAnimLayers 내 함수 구현
  • 어떤 애니메이션을 쓸 지 결정하는 역할
    • 실제 출력되는 애니메이션은 하위 클래스 ABP_Rifle/Pistol ... 등의 설정한 애니메이션 시퀀스 출력
  • WeaponType, IsJump, bCrouch 등 바인딩된 AnimInstance의 Character Movement Component을 사용한
    최종 애니메이션 결정

ABP_Locomotion

  • 무기 타입에 따라 분기된 실제 애니메이션 그래프
  • 무기타입 변경시 해당 클래스가 애니메이션 스타일을 시각적으로 변경한다.

Lyra 성능 최적화 방법

  • 이벤트 그래프 -> 멀티스레드 애니메이션 (Blueprint ThreadSafe UpdateAnimation)을 사용한 멀티스레드
  • 동기화를 데이터 Process Access를 사용한 ThradSafe 방식 사용
  • 재사용 및 유연성 고려한 Animation Layer Interface를 사용한 함수 정의

 

 

 


출처 및 참조링크

 

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/lyra-sample-game-in-unreal-engine

https://www.youtube.com/watch?v=ys_kSOKpTtg&list=PLNBX4kIrA68lSY6Pj3zDVH6kGDIMgwOvr&index=3

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/animation-blueprint-nodes-in-unreal-engine

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/animation-optimization-in-unreal-engine

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/data-validation-in-unreal-engine

https://dev.epicgames.com/documentation/ko-kr/unreal-engine/property-access-in-unreal-engine

https://daekyoulibrary.tistory.com/entry/UE5-Render-thread%EC%99%80-Animation-thread%EC%97%90-%EB%8C%80%ED%95%9C-%EC%9D%B4%ED%95%B4

+ Recent posts