언리얼 엔진 5/개발 일지

[UE5] 블루아카이브 TPS게임 개발일지 (2) - 캐릭터 state 추가, 애니메이션 개선

ciel45 2023. 12. 2. 17:03

캐릭터의 현재 상태를 나타내는 enum을 새로 만들었다. 우선 비무장 상태, 권총 무장 상태, 소총 무장 상태 3가지를 만들었다.

 

 

캐릭터의 state는 다른 여러 클래스에서 쓰일 경우가 많다. State만을 쓰기 위해서 KannaCharacter 전체를 include하는 것은 피하고 싶으므로, 별도의 헤더 파일에 state를 정의한다.

CharaterType.h에 ECharaterState 정의, uint8은 열거형 상수 값의 범위를 부호없는 8비트로 제한한 것이다. (미세한 최적화)

 

이후 KannaCharacter.h에 ECharacterState 타입 변수를 만들어주었다.

UPROPERTY(BlueprintReadWrite, meta = (AllowPrivateAccess = "true"))
ECharacterState CharacterState = ECharacterState::ECS_Unarmed;

 

이제 기존의 애니메이션 블루프린트를 state에 기반해서 작동되도록 바꾸려고 한다.

원래의 애니메이션 블루프린트는 IsFalling, IsAiming 플래그 변수를 이용해서 간단히 구현해놨었다. 

 

이러한 방식을 고집하였을 때,  캐릭터 state가 개수가 많아지고 복잡해진다면, 각 state를 나타내는 플래그 변수를 많이 넣어야 하고, 블루프린트가 지저분해질 것이다.

따라서 state에 따라 적합한 애니메이션을 재생하도록 하는 것이 목표이다.

 

 

 

 

작업에 앞서 권총을 든 상태의 Idle, Run 애니메이션을 기존 애니메이션을 편집하여 적당히 만들어주었다.

Pistol_Idle
Pistol_Run

 

 

 

 

우선 애니메이션 블루프린트가 KannaCharacter 클래스의 state를 참조하도록 하였다. 의존성을 낮추기 위해 별도의 Getter 메소드를 만들었다.

KannaAnimInstance는 애니메이션 블루프린트(ABP_Kanna)의 부모 클래스이다. NativeUpdateAnimation은 매 프레임 호출되는 함수이다. 함수의 마지막 줄이 상술한 부분이다.

 

 

이제 애니메이션 블루프린트의 AnimGraph에서 읽어온 state를 이용하여 애니메이션 출력을 처리할 것이다.

state에 따라 다른 Idle 애니메이션. Run 애니메이션도 마찬가지이다.

 

Blend Poses 노드를 이용해 enum 값에 따라 다른 포즈가 출력되도록 할 수 있다.

소총 무장 상태에 대응해서는 아직 만들지 않았다. 추후에 추가할 예정이다.

 

 

그리고 애니메이션 블루프린트(ABP_Kanna)가 너무 복잡해지지 않도록, 절차를 여러개로 분할하였다.

MainState를 만드는 블루프린트. 정지/이동, 조준/중립, 공중/지상 등의 컨디션을 판별하여 애니메이션을 제공한다.
IK Rig를 계산해서 지형에 따라 자세를 바꿔주는 블루프린트. 바로 위의 Output Pose를 Input Pose로 이어받는다.

 

최종적으로 캐릭터에 애니메이션을 적용해주는 블루프린트. 위의 두 블루프린트를 Linked Anim Graph로 가져와서 사용한다.

 

 

Linked Anim Graph를 통한 여러개의 애니메이션 블루프린트의 링크에 대한 자세한 설명은 여기를 참고하자.

https://docs.unrealengine.com/5.0/ko/animation-blueprint-linking-in-unreal-engine/

 

애니메이션 블루프린트 링크하기

애니메이션 블루프린트 링크 및 템플릿을 사용하여 애니메이션 블루프린트 로직을 모듈화합니다.

docs.unrealengine.com

 

 

 

이렇게 여러개의 애니메이션 블루프린트를 만든다면, 가장 먼저 우려되는 점은 변수의 공유일 것이다.

 

각각의 애니메이션 블루프린트는 서로 다른 클래스와 같기 때문에 각자의 변수를 가지고있다. 예를 들어, 각 블루프린트에서의 IsFalling, GroundSpeed는 원래 서로 공유하지 않는 각자의 변수이다.

 

그러나 우리가 원하는 것은 모든 블루프린트에서 변수를 공유하는 것이다.

 

예를 들면 ABP_Kanna_MainStates의 IsFalling은, 그대로 ABP_Kanna_IK에서도 사용되어야 한다.

낙하중에는 지형에 따라 자세를 바꾸지 않도록 하는 로직을 적용해야 하기 때문이다.

 

GroundSpeed 변수도 마찬가지다.

 

유니티에서였다면 이를 해결하기 위해 스크립트상으로 레퍼런스나 포인터 타입 변수를 사용해야 했겠지만, 언리얼 엔진에서는 Linked Anim Graph에서의 바인딩으로 쉽게 해결할 수 있다.

Details 패널에서 각 애니메이션 클래스의 변수들 중 무엇과 무엇을 바인딩할지, 즉 공유할 지 정해줄 수 있다. 이로서 3개의 애니메이션 블루프린트에서 동일한 변수 값을 사용할 수 있다.

 

 

 

테스트를 위해 권총을 넣고 빼는 간단한 InputAction을 만들었다. 이 역시 추후 무기 종류가 늘어남에 따라 수정하게 될 수 있다.

SwitchWeapon이 해당 인풋이다.

 

KannaCharacter.h에 캐릭터에 넣어주기 위한 UInputAction 포인터 변수도 만들어줬다.

 

 

그리고 간단한 무기 전환 코드이다. 

SwitchWeaponAction에 바인딩 되어있다. 1을 누르면 캐릭터의 state가 바뀐다.

 

이제 테스트 해볼 차례이다.

 

의도한 바대로 잘 동작하는 것을 볼 수 있다.