728x90
이 글은 Inflearn - Rookiss : 언리얼 엔진4 입문 강의를 듣고 정리한 글입니다.

 

목차.

  1. 개요
  2. 스테이트(상태) 머신 사용 : 점프
  3. 점프 애니메이션 개선

 

개요

 

플레이어의 다양한 행동에 대해서 애니메이션을 if-else문을 통해 제어할 수 있지만 이후 코드가 꼬이게 될 가능성이 매우 높습니다. 

 

if-else 문을 통해 애니메이션을 제어하고있는 모습

 

만약 각 행동에 대해 상태로 관리하면 깔끔하게  관리가 가능한데 이번 글에서 상태 머신을 사용해서 애니메이션을 관리해 보겠습니다.

 

 

스테이트(상태) 머신 사용 : 점프

 

플레이어의 움직임에 따라서 애니메이션이 작동하게 했었습니다.

 

저번까지 만든 애니메이션 블루프린트

 

여기서 점프가 추가된다면 if-else를 통해서도 구현할 수 있지만 스테이터 머신을 활용해서 점프 애니메이션을 구현해 보겠습니다.

 

AnimGraph 창에서 마우스 우클릭 -> state Machines를 검색 -> 스테이트 머신 새로 추가 클릭

 

블루프린트 스테이트 머신 새로 추가하기

 

새로 추가한 스테이트 머신을 최종 애니메이션 포즈와 연결합니다

 

스테이트 머신 -> 최종 애니메이션 포즈

 

스테이트 머신을 더블 클릭하고, 두 가지 상태를 새로 추가합니다.

이름은 각각 Ground, Jumping으로 설정하고 두 개의 상태를 각각 연결해 줍니다.

 

Ground 상태와 Jumping 상태 연결

 

AnimGraph에서 사용하던 Idle, Walk 애니메이션을 Ground 스테이트로 Ctrl + X , Ctrl + V 해서 옮긴 뒤,

출력 애니메이션 포즈와 연결해 줍니다.

 

기존 AnimGraph에 있던 애니메이션을 Ground 스테이트로 옮김

 

컴파일하고 저장한 뒤, 게임을 실행해 보면 잘 작동하는 것을 볼 수 있습니다.

 

기존 애니메이션 잘 작동하는 모습

 

이제 스페이스바를 누르면 점프를 하고 점프 애니메이션이 작동하도록 하겠습니다.

 

일단 다시 애니메이션 블루프린트로 돌아와 내 블루프린트에 눈 아이콘을 눌러보면 상속된 변수 표시가 체크 해제되어 있을 텐데 체크를 하면

전에 만들어둔 Speed 변수가 폰에서 표시되는 것을 볼 수 있습니다.

이제 점프도 변수를 활용해서 제어할 것입니다.

 

내 블루프린트에서 상속된 변수 표시하기

 

점프 기능 구현을 위해 AnimInstance 클래스에 변수를 추가해 주겠습니다.

 

.h

UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Pawn, Meta = (AllowPrivateAccess = true))
bool IsFalling;

 

.cpp

#include "MyAnimInstance.h"
#include "GameFramework/Character.h"
#include "GameFramework/PawnMovementComponent.h"
void UMyAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
	Super::NativeUpdateAnimation(DeltaSeconds);

	auto Pawn = TryGetPawnOwner();

	if (IsValid(Pawn))
	{
		Speed = Pawn->GetVelocity().Size();

		auto Character = Cast<ACharacter>(Pawn);

		if (Character)
		{
			IsFalling = Character->GetMovementComponent()->IsFalling();
		}
	}
}

 

전 코드에서 추가된 부분은 ACharacter를 캐스팅하고,

캐스팅에 성공했다면 MovementComponent를 받아와 IsFalling 함수에 접근하는 코드가 추가되었습니다.

 

언리얼 엔진에서 이런 식으로 기본적인 움직임부터 해서 낙하 등 다양한 함수가 이미 존재한다는 부분이 좋은 것 같습니다.

 

이제 키 입력을 받아와야 하니까 키 입력은 Character 클래스에 추가해 주겠습니다.

 

Character.cpp

void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAction(TEXT("Jump"), EInputEvent::IE_Pressed, this, &AMyCharacter::Jump);
....
}

 

전에 W, A, S, D 입력을 통해 움직임을 구현할 때는 UpDown(value), LeftRight(value)와 같이 함수를 정의했는데 점프는 언리얼에서 기본적으로 구현되어 있기 때문에 따로 구현할 필요는 없습니다.

 

이미 정의되어있는 Jump 함수

하지만 여전히 프로젝트 세팅을 통해서 키 입력은 설정해주어야 합니다.

 

프로젝트 세팅 -> 입력 -> 액션매핑에서 Jump 추가

전에는 축 매핑을 추가해서 좌, 우 입력키를 받아왔지만 이번에는 액션 매핑을 추가했습니다.

 

이제 컴파일 후 게임을 실행하면 점프가 잘 되는 것을 볼 수 있습니다.

 

점프 애니메이션의 추가는 매우 간단한데, IsFalling이 true일 때는 점프 애니메이션을 작동시키고 false 일때 Ground 스테이트로 넘어가서 점프 애니메이션을 종료시키면 됩니다.

 

Ground -> Jumping 트렌지션에 IsFalling True일때 Enter하게 설정

 

Jumping -> Ground 트렌지션에서는 NOT을 이용

 

이제 컴파일, 저장 후 게임을 실행하면 점프하는 순간 IsFalling 애니메이션이 작동하고 바닥에 착지하면 애니메이션을 종료시키는 것을 볼 수 있습니다.

 

아직 문제가 있는데 점프 애니메이션은 보통 점프하는 순간, 점프하는 중, 낙하, 착지 이런 식으로 다양한 애니메이션이 연결되어 점프 애니메이션이 완성됩니다.

 

이것을 위해 다른 상태를 더 추가해서 점프 애니메이션을 개선해 보겠습니다.

 

 

점프 애니메이션 개선

 

JumpEnd, JumpStart 상태 추가

 

Ground->JumpStart->Jumping->JumpEnd->Ground로 트렌지션 연결

 

그리고 각 스테이트에 들어가 적절한 애니메이션을 실행하도록 배치하면 됩니다.

제가 사용하는 애니메이션은 마침 Start와 Jumping, Fall 등 다양하게 있었습니다.

 

각 상태에 맞는 애니메이션 할당

 

애니메이션이 다른 애니메이션으로 전환될 때 자연스럽게 전환되게 하기 위해 

JumpStart -> Jumping 트렌지션에 Time Remaining 함수를 활용해

비율이 0.1보다 작게 남았으면 애니메이션이 끝난 것이라고 판단하게 해 주었습니다.

 

Time Remaining(ratio)함수 활용

 

Jumping -> JumpEnd 트렌지션은 전과 마찬가지로 IsFalling이 false일 때 작동하게 해 주었고,

JumpEnd -> Ground 트렌지션은 클릭해 보면 Automatic Rule Based...라는 체크박스가 있는데 이것을 체크하고

경과시간을 0.2로 하면 End 애니메이션이 다 끝나가면 자동으로 Ground로 상태가 넘어가게 됩니다.

 

경과시간을 조절에서 끝날 타이밍을 설정할 수 있다.

 

이제 게임을 실행해서 점프를 하면 JumpEnter, Jumping, JumpEnd 모두 자연스럽게 이어집니다.

 

와우!

728x90

+ Recent posts