UE5/Devlog

[UE5] Last Bot Standing Devlog - 14

sulfurman 2026. 2. 1. 01:37

반갑습니다.

이번 시간에는 저번시간에 언급한 1인칭 애니메이션을 위한 대대적인 개편에 대한 개발 일지를 작성하려고 합니다.

'대대적인'이라는 수식어가 들어간 만큼 많은걸 뜯어 고쳤습니다.

기존에 하드코딩되어 있는 부분이나, 작동은 잘되지만 지저분한 부분들을 수정하는 것에 집중한 작업이었습니다.

특히, 앞전에 소개한 1인칭 전용 애니메이션 에셋을 제 프로젝트에 이식하는 작업이 대부분이었는데
이게 정말 힘들었네요.

2주동안 블루프린트들이랑 씨름을 하며 기반을 다지면서 이렇게 글을 쓸 수 있게 되었습니다.


1. 애니메이션 작동 파이프라인 설계

 언리얼에서 애니메이션 블루프린트(ABP)는 하나의 공장이라고 생각하면 된다.

ABP는 인풋 포즈와 아웃풋 포즈 사이 노드들을 연산해 출력하는 단순한 구조이고,
ABP에 ABP를 삽입 할 수 도 있기에, 입맛에 맞게 공정을 설계할 수 있다.

 

 내 프로젝트의 기존 애니메이션 작동은 오로지 ABP_PUBGCharacter라는 애니메이션 블루프린트에서만 이루어져 있었다.

GASP 에셋 (캐릭터의 기본 움직임, 파쿠르등을 담당) 전신에 무기를 장착한 애니메이션을 블렌딩하는 단순한 구조였다.

이 구조의 가장 심각한 문제가 확장이 정말 힘들다는 것이었다.

총기 모션하나를 추가하려면 노드를 이것저것 추가하는게 여간 까다로운게 아니었기에, 반드시 개편이 필요했다.

 

 나의 목적은 1인칭과 3인칭의 자유로운 전환이었고, 각각의 ABP는 어느정도 모듈화가 되어있는 상태였다.

이 둘을 병합하는 것을 최우선 과제로 삼고 작업을 진행했다.

 

 각각의 ABP들은 완전히 별개의 에셋이기에 서로 소통하기 위해서는 변수와 메소드들 수정하는 작업이 선행되었고,

기본이 되는 동작에 필요한 동작들을 쌓아 올려가는 방식으로 파이프라인을 설계했다.

 

애니메이션 작동 파이프라인

 

 각각의 에셋에 존재하는 ABP를 수정해 내 프로젝트 맞춤형으로 커스텀하고 연결한 뒤,
최종 출력에서 상황에 맞게 적절히 블렌딩 해줄 수 있는 파이프라인을 설계했다.

모든 ABP는 독립적이고, 서로에게 간섭하는 경우는 블렌딩할 때 뿐인데, 이렇게 설계한 이유는

추후에 추가하고 싶은 동작이 있으면 모듈화된 ABP를 블럭처럼 끼웠다 뺄 수 있는 확장성에 용이했기 때문이다.

 

2. 애니메이션 데이터 구조 관리(Anim Settings)

 기존 FPS 애니메이션 에셋이 관리하는 데이터 구조체에서
필요한 부분만 체리피킹해 애니메이션 세팅을 새롭게 설계했다.

 

 ABP는 캐릭터 블루프린트(CBP)으로부터 얻은 인풋들을 캐싱한 변수들을 통해
어떤 애니메이션을 재생할지 선택하는데, 이 부분을 막무가내로 노드로 나열하게 되면 지옥이 펼쳐진다.

도대체 뭐가 뭔 노드였고, 어떤 동작을 언제 수행하는지도 모르는
그야말로 스파게티를 넘어서서 비빔밥이 완성된 모습을 볼 수 있을 것이다.

 

그래서 언리얼 엔진에서 제공하는 자료구조로 잘 정리해서 언제 어느 상황에 무엇을 재생할 지에 대한 정보를 담아야만 한다.

나는 크게 두개로 분류했는데, WeaponAnimSettings(WS_총기이름)와 CharacterAnimSettings(CS_총기이름)이다.

WeaponAnimSettings, CharacterAnimSettings

 

 WeaponAnimSettings은 총기의 다양한 애니메이션, 스켈레탈 메시, 반동 세팅, 총기 사운드를 담은 DataAsset이고,

CharacterAnimSettings은 해당 총기에 대한 캐릭터의 다양한 애니메이션, 포즈 오프셋(총을 잡은 캐릭터의 포즈 설정값)을 담은 DataAsset이다.

 

ABP는 CBP로부터 캐싱된 변수를 가지고 그 상황에 맞는 애니메이션을 WS와 CS에서 가져와 재생한다.

예를 들어 캐릭터가 MX16A4라는 총기를 들고 재장전을 한다고 해보자

 

1. ABP는 CBP로부터 WantsToReload라는 불리언 값, 약실에 총알 유무를 캐싱된 변수를 통해 확인한다.

2. 확인해보니 WantsToReload는 참이고, 약실에는 총알이 없음을 확인하고 PrimaryReload를 WS와 CS에서 꺼내와 재생한다.

 

대충 이런식으로 진행된다.

 

 

 기존 에셋의 데이터 구조가 진짜 너무 복잡하고 주석도 없어서 눈물을 머금으며 분석한 기억이 난다...

코드로 되어있었으면 제미나이로 딸깍 가능인데, 블루프린트라 손으로 끄적일 수 밖에 없었다.

 

3. Gameplay Camera 플러그인을 이용한 카메라 설정

 이전에 언급을 한번 했는데, 내 프로젝트는 Gameplay Camera라는 실험적인 카메라 플러그인을 사용하고 있다.

아주 쉽게 이야기해보면, 카메라 설정을 블루프린트로 세팅할 수 있게끔 만든 플러그인이라고 할 수 있겠다.

 

Get_CharacterPropertiesForCamera

 

 먼저 CBP의 인터페이스로 카메라에 사용할 변수들을 얻을 수 있는 Getter 함수를 생성한다.

여기서 캐릭터의 상황에 맞춰 어떤 카메라로 전환할 지에대한 정보를 Enum으로 반환해준다.

(캐릭터가 조준함 -> WantToAim 참으로 변경 -> ECameraMode를 Aim으로 전환)

CameraDirector_SandboxCharacter

 

 이 함수는 CameraDirector 블루프린트에서 사용된다.

해당 블루프린트는 Event Run Camera Director라는 이벤트를 통해 실행 되는데,
해당 이벤트는 Gameplay Camera를 컴포넌트로 가지고 있는 캐릭터가 해당 디렉터를 사용하면 자동으로 호출되고,
이벤트는 캐릭터에 Gameplay Camera가 존재하는 한, 매 틱 작동한다.

그렇기에, 매 순간 카메라가 어떤 상태인지 확인하면서 즉각적으로 카메라를 원하는 위치로 이동시킬수 있게 되는 것이다.

 


결과

 

이동할 때 자연스러운 팔 동작이 필요해 보입니다.
너무 정적으로 움직임...

이후에 총기류 추가, 카메라 전환시 끊김 해결, 다양한 총기 조작 애니메이션 추가 등등 할게 많습니다.

 

이렇게 다인칭 애니메이션을 위한 기반을 마련하니 속이 시원하네요.

오랜 숙원 사업 같은거 였는데, 다행히 생각보다 빠르게 끝난 것 같습니다.

지난 주만 해도 그냥 떄려 칠까까지 생각한 것이 무색하게 결과물이 잘 나와서 다행이라 생각이 듭니다.

 

그럼 여기서 마치고 다음 개발일지 때 뵙겠습니다.