FSM을 통한 애니메이션 설계(점프)

유영준·2023년 1월 5일
0
post-thumbnail

그동안은 최대한 블루프린트를 제외하고 C++만을 이용한 프로그래밍을 해왔다
그러나 애니메이션에서의 블루프린트가 굉장히 강력하기 때문에
애니메이션을 하는 동안은 블루프린트를 쓸 예정이다


2023-01-07 애니메이션 리타게팅 방식 추가

FSM을 이용한 Idle 상태와 Run 상태 구분

먼저 AnimInstance 클래스를 만들어주자
AnimInstance 는 언리얼 엔진에서 블루프린트를 통한 애니메이션 제작 도구이다

All Classes -> AnimInstance를 통해 만들 수 있다

헤더 내용을 작성해준다

class ARENABATTLE_API UABAnimInstance : public UAnimInstance
{
	GENERATED_BODY()
	
public:
	UABAnimInstance();
	virtual void NativeUpdateAnimation(float DeltaSeconds) override;

private:
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Pawn, Meta = (AllowPrivateAccess = true))
	float CurrentPawnSpeed;
};

CurrentPawnSpeed 값을 폰의 속도와 연동해 속도가 0초과라면 움직임이라 판단하고
애니메이션이 움직이도록 해줄 것이다
NativeUpdateAnimation() 함수를 통해 폰의 정보를 가져올 것이다

이후 cpp 파일을 작성해준다

UABAnimInstance::UABAnimInstance()
{
	CurrentPawnSpeed = 0.0f;
}

void UABAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
	Super::NativeUpdateAnimation(DeltaSeconds);

	auto Pawn = TryGetPawnOwner();

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

TryGetPawnOwner() 함수를 통해 Pawn을 찾고,
Pawn 이 있다면 CurrentPawnSpeed 를 폰의 속도로 동기화 해주는 코드이다

이제 그렇다면 블루프린트를 통해 실제로 애니메이션을 연결해주도록 하자


FSM 제작

언리얼 엔진 또한 유니티와 동일하게 FSM(Finite State Machine)으로 애니메이션을 제작하게 되어있다

FSM이란 여러개의 상태가 존재하고 그 상태들을 조건으로 엮는 기계를 뜻한다
우리는 땅에 있는지, 공중에 있는지 등을 나눠 애니메이션을 만들려 한다

먼저 상태(State)를 만들어줘야 하니 우클릭 후 state machine 을 만들어준다

이름을 BaseAction으로 바꾸고, 애니메이션을 연결해주었다

BaseAction에 들어간 후, add State를 통해 Ground state를 만들고,
Entry에서 Ground로 연결시켜주었다

Ground 안에서, 에셋 브라우저에 있는 WarriorRun과 WarriorIdle을 Ground 상태창에 올려둔다

우리는 CurrentPawnSpeed 변수가 0 초과시 Run, 아니라면 Idle 상태를 만들것이다

먼저 CurrentPawnSpeed 변수를 Ground 상태창에 올려두고


초록색 노드를 눌러 비교 연산자 >를 찾는다

greater 노드에서는 빨간 노드(boolen)에서 Blend Poses by bool 을 만들어준다

이후 true일때는 Run, false 일때는 Ilde 애니메이션을 연결해주고,
블랜딩 되는 포즈를 Output에 연결해준다
blend Time은 적당히 자연스럽게 0.3 정도를 줬다


(완성된 모습)

컴파일 후 에디터 오른쪽 하단에서 Current Pawn Speed를 바꿔보며 잘 움직이는지 확인해 보자


jump 모션 제작

먼저 input 창에 jump 액션을 추가해준다

다른 모션들은 함수를 선언해주었지만, ACharacter 클래스에는 기본적으로 Jump 함수가 내장되어 있다
그렇기에 Jump 함수의 바인딩만 해주면 된다

이번에는 Jump 중 착지할 때를 인지하도록 하겠다
Pawn 에서 제공하는 IsFalling() 함수를 통해 가능한데
animinstance 클래스에 IsInAir 변수를 두고 그 상태를 지켜보도록 하겠다

생성자에서 초기화해주는 것을 잊지말고

이후 cpp 파일에서 IsInAir변수를 IsFalling 과 연동시켜주자

void UABAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
	Super::NativeUpdateAnimation(DeltaSeconds);

	auto Pawn = TryGetPawnOwner();

	if (IsValid(Pawn))
	{
		CurrentPawnSpeed = Pawn->GetVelocity().Size();
		auto Character = Cast<ACharacter>(Pawn);
		if (Character)
		{
			IsInAir = Character->GetMovementComponent()->IsFalling();
		}
	}
}

여기까지 왔다면 이제 블루프린트에서 점프 모션을 추가해 줄 차례인데,
우리가 애니메이션에는 점프가 없기 때문에 언리얼 엔진 기본 마네킹 모션을 리타게팅해서 가져올 것이다


애니메이션 리타게팅

UE4에서는 리타게팅 매니저를 통해 리타게팅을 하였는데,
현재 UE5에서는 그 방법이 되지 없어진 상황이다

이 방식은 모든 스켈레톤에 가능한지는 모르겠으나, 현재 나의 상황에는 아무 문제가 없었기에 일단 기재하려고 한다

먼저 기본 애니메이션에서 Jump , Fall_loop , Land 3가지 애니메이션을 복사해준다

이 3가지 애니메이션을 우리 애니메이션 폴더로 붙여넣기 후, 우리 캐릭터의 스켈레톤으로 바꿔준다

이후 이름을 WarriorJumpStart 등으로 바꿔주자


2023-01-07 추가 리타게팅 방식

Skeltal Mesh를 선택해 리타게팅 하는 방식을 찾았다

Duplicate and Retarget Animation Asset 을 클릭후 IK Retargeter 항목을 RTG_Mannequin으로 설정

왼쪽에는 소스가 될 스켈레탈 메쉬, 오른쪽에는 내가 애니메이션을 얻고 싶은 스켈레탈 매쉬를 놓고 리타겟 버튼을 눌러준다

완성된 모습


블루프린트에서는 JumpStart, JumpLoop, JumpEnd 3가지 상태를 만들어주고,
각 각 Ground -> JumpStart -> JumpLoop -> JumpEnd -> Ground 로 이어주자

각각에 State에는 자신의 애니메이션을 연결해준다

Ground 에서 JumpStart 로 가는 화살표를 클릭 후, Is In Air 상태일때를 만들어주고,

JumpLoop 에서 JumpEnd 로 가는 화살표에는 Is In Air 에 Not 을 붙여주자

JumpStart -> JumpLoopJumpEnd -> Ground 는 애니메이션이 끝나면
자동으로 다음 애니메이션이 나오는 Automatic Rule Based in Sequence in Player State를 체크하자

이후 Is in Air 를 체크 해보며 잘 작동하는지 확인해보자

마지막으로 인게임 내에서도 실험을 해보자

profile
토비폭스가 되고픈 게임 개발자

0개의 댓글