본문 바로가기

게임프로그래밍/실습1

[언리얼 실습] 20. 무장 해제 애니메이션 적용


목차

  1. 무장해제 애니메이션 만들기
  2. C++에서 재생하기

1. 무장해제 애니메이션 만들기

 

먼저 무장 애니메이션과 무장 해제 애니메이션을 구하자. 그리고 이것들을 애니메이션 몽타주에서 재생할 것이다.

 

 

애니메이션을 설정하자. 이제 이 몽타주를 재생하기만 하면 된다.


2. C++에서 재생하기
UPROPERTY(EditDefaultsOnly, Category = "Montage")
UAnimMotage* EquipMontage;

 

캐릭터 헤더파일에 몽타주를 담을 변수를 선언해주자.

 

이제 이 몽타주를 재생하면 된다.

 

void AKnight::EKeyPressed()
{
	AWeapons* OverlappingWeapon = Cast<AWeapons>(OverlappingItem);
	if (OverlappingWeapon)
	{
		OverlappingWeapon->Equip(GetMesh(), FName("RightHandSocket"));
		CharacterState = ECharacterState::ECS_EquippedOneHandWeapon;
	}
}

 

cpp 파일에서 기존에 있는 E 입력 함수를 수정할 것이다.

 

if (ActionState == EActionState::EAS_Unoccupied && CharacterState != ECharacterState::ECS_Unequipped)

 

해당 구문을 추가해서 캐릭터가 unoccupied (제어가 가능한 상태) 인지 아닌지랑 무기를 장착하고 있는지 아닌지를 알아본다.

 

위 구문을 직접 넣기보다는 함수로 구현해서 넣도록 하자.

 

bool AKnight::CanDisarm()
{
	return ActionState == EActionState::EAS_Unoccupied &&
		CharacterState != ECharacterState::ECS_Unequipped;
}

 

다음과 같이 정의를 하고 이 함수를 if 조건문에 넣을 것이다. 이제 해당 조건에 부합하면 무장해제를 할 것인데 애니메이션 재생하는 부분은 다시 함수로 정의하려고 한다.

 

// 헤더파일
void PlayEquipMontage(FName SectionName);

// cpp 파일
void AKnight::PlayEquipMontage(FName SectionName)
{
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	if (AnimInstance && EquipMontage)
	{
		AnimInstance->Montage_Play(EquipMontage);
		AnimInstance->Montage_JumpToSection(SectionName, EquipMontage);
	}
}

 

이제 섹션 네임을 알아낼 방법을 만들어야한다. 무장 해제를 할 수 있는지 여부를 알아내는 함수는 만들었으니 무장을 할 수 있는지 알 수 있는 여부를 아는 함수를 만들어야 한다.

 

bool AKnight::CanArm()
{
	return ActionState == EActionState::EAS_Unoccupied&&
		CharacterState == ECharacterState::ECS_Unequipped;
}

 

간단하게 위 처럼 만들면 된다.

 

다만 현재 CanArm 함수와 CanDisarm 함수만으로는 무기의 소지 여부를 알 수 없다. 이 두 조건만 쓰면 무기를 가지고 있지 않아도 무장과 무장해제를 할 수 있을 것이다.

 

그렇기 때문에 무기 변수를 만들어 무기를 실제로 소유하고 있는지를 알아낼 것이다.

 

UPROPERTY(VisibleAnywhere, Category = "Weapon")
class AWeapons* EquippedWeapon;

 

헤더 파일에 변수를 선언하자.

 

이제 이 변수는 무기를 처음 장착할때 설정해줄 것이다.

 

void AKnight::EKeyPressed()
{
	AWeapons* OverlappingWeapon = Cast<AWeapons>(OverlappingItem);
	if (OverlappingWeapon)
	{
		OverlappingWeapon->Equip(GetMesh(), FName("RightHandSocket"));
		CharacterState = ECharacterState::ECS_EquippedOneHandWeapon;
		OverlappingItem = nullptr;
		EquippedWeapon = OverlappingWeapon;
	}
}

 

무기를 장착할때 OverlappingItem = nullptr; 를 통해 겹쳐진 아이템을 비워야 한다. 왜냐하면 아이템을 비우지 않으면 E키를 누를때마다 계속 함수가 실행될 것이기 때문에 이를 방지해야하기 때문이다. 그 후 오버랩된 무기를 장착된 무기 포인터에 저장해주자.

 

이제 조건문을 수정하여 장착된 무기가 있는지 확인하면 된다.

 

bool AKnight::CanAttack()
{
	return ActionState == EActionState::EAS_Unoccupied &&
		CharacterState != ECharacterState::ECS_Unequipped &&
		EquippedWeapon;
}

bool AKnight::CanDisarm()
{
	return ActionState == EActionState::EAS_Unoccupied &&
		CharacterState != ECharacterState::ECS_Unequipped &&
		EquippedWeapon;
}

 

이제 E키를 눌렀을 때 반응을 정의하자.

void AKnight::EKeyPressed()
{
	AWeapons* OverlappingWeapon = Cast<AWeapons>(OverlappingItem);
	if (OverlappingWeapon)
	{
		OverlappingWeapon->Equip(GetMesh(), FName("RightHandSocket"));
		CharacterState = ECharacterState::ECS_EquippedOneHandWeapon;
		OverlappingItem = nullptr;
		EquippedWeapon = OverlappingWeapon;
	}
	else if (CanDisarm())
	{
		PlayEquipMontage(FName("Unequip"));
		CharacterState = ECharacterState::ECS_Unequipped;
	}
	else if (CanArm())
	{
		PlayEquipMontage(FName("Equip"));
		CharacterState = ECharacterState::ECS_EquippedOneHandWeapon;
	}
}

 

컴파일을 하고 동작을 잘 하는지 확인하자. 플레이를 하기 전 캐릭터 블루프린트에서 몽타주를 설정하는 것을 잊으면 안된다.

 

이렇게 하면 동작이 정상적으로 되는 것을 볼 수 있는데 현재는 애니메이션이 재생만 될 뿐 실제로 무기가 손에서 사라지거나 하지는 않는다.

 

다음에는 실제로 무장해제를 하고 무장을 하는 법을 알아보자.