Unreal Engine, Animation 이동 - 매 프레임마다 변수 값 갱신 최적화

이전 시간에 만든 Animation 하체의 상태 전이까지 완료하였다.
이전 글에 이어서 캐릭터가 움직이면 애니메이션이 움직이지 않는 것을 확인할 수 있었는데, 이제 캐릭터가 움직이면 다리를 움직이는 애니메이션 함수를 만들어 주도록 한다.

튜토리얼에는 Event Blueprint Update Animation 활용한 방법이 있으나, Lyra 에서는 최적화된 애니메이션이 있으니 이 방법을 사용하도록 한다.

이전에 작업한 애니메이션 블루프린트를 다시 열도록 한다.

Content
└─Game
   └─Animations
      └─ABP_Warrior_Base (*)

Function - Blueprint Thread Safe Update Animation

블루프린트 좌측 하단의 Functions "Override" 표시된 부분을 클릭하여 "Blueprint Thread Safe Update Animation"이름의 Anim Instance 를 추가하도록 한다.

Lyra의 독자적인 방법은 아니고 공식 홈페이지에서 애니메이션 최적화 문서로 확인할 수 있다.

https://dev.epicgames.com/documentation/en-us/unreal-engine/animation-optimization-in-unreal-engine?application_version=5.4

문서의 포인트는 다음과 같이 되어있다.

  • 애니메이션 처리에 많은 연산이 필요해 최적화가 필요함
  • 병렬 처리로 멀티 쓰레드 환경으로 게임쓰레드와 워커쓰레드로 애니메이션 연산함
  • 일반적인 메인 로직에 이벤트 그래프를 작성하면 병목현상이 발생할 수 있음 - 이벤트 그래프는 Tick이 느리다.
  • 쓰레드 세이프 함수를 별도로 만들고 Tick 이 느려지는 현상을 개선함

즉, BlueprintThreadSafeUpdateAnimation 는 병렬처리도 되고 시스템 성능도 개선되었다.
이벤트 그래프에서 작성할 때와 차이점은 Character 갖고 와서 작업을 했지만, ThreadSafe 함수는 안전한 함수로 Thread Safe 하지 않은 Character 갖고 오는 방식은 권장하지 않고 있다. ThreadSafe 함수는 ThreadSafe 처리된 함수와 변수끼리만 호출하도록 권장한다.

이제 Sequence 노드를 추가하도록 한다.

Then 1 번 핀은 Velocity 를 추가하도록 할 것이다.


Velocity Then 1 작성

Velocity 변수로 하고 싶은 것은 이 값에 따라 GroundSpeed, Direction 변수의 값을 연산하고 싶은 것이다. 그럼 Velocity에 따라서 캐릭터 애니메이션이 빠르거나 느리게 동작할 것이다.

추가로 Property Access 라는 노드도 추가하고 TryGetPawnOwner > GetMovementComponent > Velocity 라는 외부 변수를 불려오도록 한다.

그리고 내장 변수로 Getter(Velocity), Setter(Velocity), Vector Length XY, Setter(Ground Speed), Setter(Direction), Property Access(TryGetPawnOwner.GetActorRotation) 노드를 불려오도록 한다.

  • Sequence 노드 out(Then1) 핀을 Setter(Velocity) in 핀으로 연결
  • Property Access(...Velocity) 노드 out 핀을 Setter(Velocity) in(Value) 핀으로 연결
  • Setter(Velocity) out(Return) 핀을 Setter(Ground Speed) in 핀으로 연결
  • Setter(Velocity) out(Value) 핀을 Vector Length XY in 핀으로 연결
  • Vector Length XY out(Return) 핀을 Setter(Ground Speed) in(Value) 핀으로 연결
  • Getter(Velocity) out(Return) 핀을 Calculate Direction in 핀으로 연결
  • Property Access(...GetActorRotation) out 핀을 Calculate Direction in(Value) 핀으로 연결
  • Setter(Groud Speed) out(Return) 핀을 Setter(Direction) in 핀으로 연결
  • Calculate Direction out(Return) 핀을 Setter(Direction) in(Value) 핀으로 연결

전체적인 그림은 아래 사진과 같이 연결되도록 한다.


ShouldMove Then 2 작성

Setter(ShouldMove) 노드를 추가한다.

  • Sequence Then 2 핀을 추가하여 Setter(ShouldMove) 와 연결한다.

IsCrouching Then 3 작성

Setter(IsCrouching), Setter(IsFalling) 노드를 추가한다.

  • Sequence Then 3 핀을 추가하여 Setter(isCrouching) 핀과 연결한다.
  • Setter(isCrouching) out(Return) 핀을 Setter(IsFalling) 핀과 연결한다.

GetCharacterMovementComponent 함수 생성

이제 변수 ShouldMove, IsChrouching, IsFalling 를 간략하게 연결하였는데, 캐릭터 데이터를 받아오는 함수가 없으므로 추가해야한다. 캐릭터 이동시 컴포넌트를 받아와 해당 상태 변수들을 업데이트 하도록 할 것이다.

새로 추가할 함수는 GetCharacterMovementComponent 이름으로 지어주도록 한다.
그리고 우측 Details의 Outputs 항목을 ReturnValue 이름으로 CharacterMovementComponent 클래스를 추가하도록 한다.

이제 해당 노드들을 추가하도록 한다.

  • Property Access: TryGetPawnOwner.GetMovementComponent 선택하여 추가
  • Cast To CharacterMovementComponent
  • Return Node 1번 노드
  • Return Node 2번 노드

Pin 연결은 다음과 같이 연결한다.

  • Get Character Movement Component out(Return) 핀은 Cast To CharacterMovementComponent in 핀으로 연결한다.
  • Property Access out(Return) 핀은 Cast To CharacterMovementComponent in(Object) 핀으로 연결
  • Cast To CharacterMovementComponent out(Return) 핀은 Return Node(1번 노드) in핀으로 연결
  • Cast To CharacterMovementComponent out(Cast Failed) 핀은 Return Node(2번 노드) in 핀으로 연결
  • Cast To CharacterMovementComponent out(Object) 핀은 Return Node(1번 노드) in(ReturnValue) 핀으로 연결

노드 연결 관계를 사진과 같이 확인할 수 있다.

마지막으로 좌측 Function 에서 Get Character Movement Component 클릭 하고 우측 Detail 에서 Pure를 선택해주도록 한다.

이제 이 Pure한 Get Character Movement Component 를 호출할 수 있고, CharacterMovementComponent 타입으로 반환할 수 있게 되었으니 사용해보도록 한다.

이 함수는 UpdateAnimation 함수에서 작업한 ShouldMove, IsChrouching, IsFalling 상태 변수에서 추가 작업을 하도록 한다.


ShouldMove Then 2 추가 작업

Pure로 설정한 GetCharacterMovementComponent 를 호출할 수 있게 되었으니, 노드를 추가하도록 한다.

  • Property Access(GetCharacterMovementComponent.GetCurrentAcceleration)
  • Vector Is Zero
  • AND 수학 노드
  • NOT 수학 노드
  • Greater 연산자 노드
  • Getter(Ground Speed)

PIN 연결하기

  • Property Access out(Return) 핀을 Vector Is Zero In 핀으로 연결
  • Vector Zero Out 핀을 NOT In 핀으로 연결
  • NOT Out 핀을 AND In 2번 인자 핀으로 연결
  • Ground Speed Out 핀을 Greater(3.0) In 핀으로 연결
  • Greater Out 핀을 AND In 1번 인자 핀으로 연결
  • AND Out 핀을 Setter(ShouldMove) In 핀으로 연결

IsCrouching Then 2 추가 작업

Property Access (GetCharacterMovement.IsCrouching) 추가하여 IsCrouching 노드 In 2번 인자값으로 연결한다.


IsFalling Then 2 추가 작업

Property Access (GetCharacterMovement.IsFalling) 추가하여 IsFalling 노드 In 2번 인자값으로 연결한다.


이제 이전시간에 CopyPose 도 올바르게 설정되어있다면 캐릭터가 정상적으로 무빙, 점프, 낙하 애니메이션이 정상적으로 동작 할 것이다.