언리얼 엔진 5/개발 일지

[UE5] 블루아카이브 TPS게임 개발일지 (40) - 장전 애니메이션 구현 1

ciel45 2024. 1. 14. 11:00

이제 실제로 장전 애니메이션을 재생할 차례이다.

 

Mixamo에서 받은 장전 애니메이션은 탄창을 넣는 것까지만 있고, 슬라이드를 당기는 것은 없었다.

 

개인적으로 꼭 넣고싶던 부분이기에, 애니메이션 시퀀스 편집창에서 수작업으로 추가해주었다.

마지막에 ReloadEnd 애니메이션 Notify가 들어가있는데, 재장전을 끝내는 이벤트로써 활용할 것이다.

 

 

 

 

우선 CharacterStates.h의 ActionState에 재장전 스테이트를 추가해주었다.

애니메이션 블루프린트가 현재 ActionState에 따라 애니메이션을 재생하고 있기 때문에, Reloading 스테이트도 추가해주는 것이다.

UENUM(BlueprintType)
enum class EActionState : uint8
{
	EAS_Neutral UMETA(DisplayName = "Neutral"),
	EAS_Attacking UMETA(DisplayName = "Attacking"),
	EAS_Rolling UMETA(DisplayName = "Rolling"),
	EAS_Aiming UMETA(DisplayName = "Aiming"),
	EAS_Reloading UMETA(DisplayName = "Reloading")
};

 

 

이제 애니메이션 블루프린트에서 Reload 스테이트를 새로 하나 만들고, OnGround에서 전환될 수 있도록 하였다.

전환 조건에서 ActionState를 사용하고 있는 것을 볼 수 있다.
Reload 스테이트 내부이다. Layered blend per bone을 사용하였다.

 

Layered blend per bone은 조준한채의 걸음을 구현할 때도 사용한 노드이다.

특정 뼈 외에는 노드의 Base Pose의 애니메이션을, 특정 뼈와 그 자식 뼈들은 Blend Poses의 애니메이션을 사용하도록 할 수 있다.

 

우측 디테일 패널을 보면, Spine을 그 특정 뼈로 설정해둔 것을 볼 수 있다. Spine은 상체의 시작이 되는 뼈이므로, 재장전 애니메이션의 상체 부분만을 사용하겠다는 의미이다.

Base Pose로 들어간 것은 평시 이동을 담당하는 Ground Locomotion의 포즈이다. 

즉, 이동하면서 재장전을 할 수 있다.

 

 

ActionState의 전환은 코드에서 담당할 것이다.

우선 KannaCharacter에서 재장전을 시작할 때, 재장전을 끝낼 때에 실행되는 함수를 다음과 같이 만들었다.

void AKannaCharacter::Reload()
{
	if (CurrentWeapon)
	{
		ReleaseAim();
		ActionState = EActionState::EAS_Reloading;
	}
}

void AKannaCharacter::ReloadEnd()
{
	if (CurrentWeapon)
	{
		CurrentWeapon->Reload(); // 총의 재장전을 인터페이스에 delegate
		ActionState = EActionState::EAS_Neutral;
	}
}

그런데, Reload 함수는 인풋에 바인딩이 되어있지만 ReloadEnd는 자동으로 호출되지 않는다.

따라서 ReloadEnd는 아까 애니메이션 Notify에서 호출하도록 하면된다.

이를 위해서는 ReloadEnd를 BlueprintCallable로 만들어줘야한다.

	UFUNCTION(BlueprintCallable)
	void ReloadEnd();

그리고 AnimNotify에서 이 함수를 호출하도록 한다.

 

이렇게 스테이트의 전환이 되도록 하였다.

이제 R을 누르면 재장전 애니메이션이 재생되고, 탄약 개수가 업데이트된다.

 

예외 상황으로, 조준 상태에서 재장전을 누르고 조준을 풀면 장전을 중단하는 문제가 있었다.

조준을 해제하면 ReleaseAim 함수가 호출되는데, 여기서 스테이트를 Neutral로 바꾸던게 문제였다.

 

따라서 이 상황에 대한 예외처리를 해주었다.

void AKannaCharacter::ReleaseAim()
{
	if (ActionState != EActionState::EAS_Reloading) // 장전 중이었을 때는 조준을 풀어도 계속 장전하도록
	{
		ActionState = EActionState::EAS_Neutral;
	}

	if(!IsInCover)
		GetCharacterMovement()->MaxWalkSpeed = 400.f;
		//SetNeutralStateSpeed();

	GetCharacterMovement()->bOrientRotationToMovement = true;
}

 

 

 

 

 

덤으로, 권총을 쏠 때의 슬라이드 효과도 꼭 넣고싶던 부분이라, 다음과 같이 만들었다.

Montage 플레이 용 슬롯만 있는 애니메이션 블루프린트. 슬롯이 없으면 Montage를 재생할 수 없다.
슬라이드 애니메이션 몽타주이다. 미리 권총을 리깅해두었기에 만드는 것이 수월했다.

 

Pistol.cpp의 Fire 함수 안에 다음과 같은 코드를 추가했고,

	UAnimInstance* AnimInstance = GunMesh->GetAnimInstance();
	if (SlideMontage && AnimInstance)
	{
		AnimInstance->Montage_Play(SlideMontage);
	}

SlideMontage를 다음과 같이 할당해주었다.

 

 

 

 

 

 

이제 장전 사운드를 넣어보려고 한다.