Infinite Fighter 개발일지 (5)

유영준·2023년 4월 9일
0

UE5 UNSEEN

목록 보기
5/18
post-thumbnail

2023.04.03 ~ 2023.04.09 개발일지

추가한 부분

Weapon 추가

그동안은 소캣에 미리보기로만 넣어두었던 무기를 이제 액터로서 구현했다

무기는 등에 매거나 손에 잡을 수 있어야 하기 때문에 둘 다 소켓을 만들어주었다

(각 각 spine_01 과 hand_r에 소켓을 만들었다)

발도 납도를 취할때, 두 소켓의 무기가 겹치는 지점을 노티파이를 통해 체크해주었다

이 부분에서 무기를 등에 부착시키거나, 손에 부착시키도록 하겠다

이때, 애니메이션 상의 어색한 부분들은 키값을 바꿔가며 맞춰주었다

이때 노티파이에는 느슨한 결합을 위해 델리게이트를 사용했다

IFCharacterAnimInstance

// IFCharacterAnimInstance.h

#include "CoreMinimal.h"
#include "Animation/AnimInstance.h"
#include "IFCharacterAnimInstance.generated.h"

DECLARE_DELEGATE(FOnAxeDrawDelegate);
DECLARE_DELEGATE(FOnAxeSheatheDelegate);

...
UCLASS()
class INFINITEFIGHTER_API UIFCharacterAnimInstance : public UAnimInstance
{
	GENERATED_BODY()
public:

	FOnAxeDrawDelegate OnDraw;

	FOnAxeSheatheDelegate OnSheathe;

	...
    
}


==============================================================

// IFCharacterAnimInstance.cpp

void UIFCharacterAnimInstance::AnimNotify_SheatheWeapon()
{
	OnSheathe.Execute();
}

void UIFCharacterAnimInstance::AnimNotify_DrawWeapon()
{
	OnDraw.Execute();
}

노티파이에서는 델리게이트를 호출하는 역할만 수행하고

IFCharacter.cpp

void AIFCharacter::PostInitializeComponents()
{
	Super::PostInitializeComponents();

	// cast IFCharacterAnimInstance to Character's AnimInstance
	AnimInstance = Cast<UIFCharacterAnimInstance>(GetMesh()->GetAnimInstance());
	
	// Binding the Delegates
	AnimInstance->OnDraw.      BindUObject(this, &AIFCharacter::Draw);
	AnimInstance->OnSheathe.BindUObject(this, &AIFCharacter::Sheathe);
}

void AIFCharacter::Draw()
{
	FName WeaponSocket(TEXT("Weapon_R"));

	Axe->DetachFromActor(FDetachmentTransformRules::KeepRelativeTransform);
	Axe->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetIncludingScale, WeaponSocket);
}

void AIFCharacter::Sheathe()
{
	FName BackSocket(TEXT("Weapon_Back"));

	Axe->DetachFromActor(FDetachmentTransformRules::KeepRelativeTransform);
	Axe->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetIncludingScale, BackSocket);
}

캐릭터에서 무기가 장착되는 것을 구현 후 델리게이트에 등록시켜주었다

완성된 모습은 다음과 같다


공격 추가

공격은 몽타주를 통해 구현했다

이때 몽타주 그룹을 나누고 다음 액션이 가능한 순간 이후부터 입력이 추가로 들어온다면 다음 공격이 가능하게끔 구현했다

IFCharacterAnimInstance.cpp

void UIFCharacterAnimInstance::PlayWeakAttackMontage()
{
	if (bCanDoNextAction)
	{
		AttackCombo++;
		if (GetAxeHolding())
		{
			if (!bIsAttackPlaying)
			{
				Montage_Play(WeaponWeakAttackMontage, 1.2f);
				bIsAttackPlaying = true;
			}
			else
			{
				Montage_JumpToSection(GetAttackMontageSection(AttackCombo));
			}
		}
		else
		{
			if (!bIsAttackPlaying)
			{
				Montage_Play(UnArmWeakAttackMontage);
				bIsAttackPlaying = true;
			}
			else
			{
				Montage_JumpToSection(GetAttackMontageSection(AttackCombo));
			}
		}

	}
}

const FName UIFCharacterAnimInstance::GetAttackMontageSection(const int32& Section)
{
	return FName(*FString::Printf(TEXT("Attack%d"), Section));
}

입력이 오면 몽타주의 다음 섹션을 플레이 하는 방식으로 구현했다

이렇게 3가지 타입의 공격을 준비했다


(맨손 약공격 3연타)


(맨손 강공격)


(무기 약공격 3연타)

무기 강공격을 추후 추가해줄 예정이다

이때 공격 모션들은 가만히 서서 하는 것이 어색해 보이기에 루트모션을 걸고, 앞으로 전진하도록 수정했다


카메라 전환 관련

레퍼런스로 삼고 있는 갓오브워(2018)의 경우,

캐릭터가 행동 중이라면 언제나 캐릭터가 카메라의 회전을 따라가고, 그렇지 않다면 캐릭터 주위를 카메라가 돌 수 있다

이를 구현해주기 위해서 2가지 기법을 사용해보았다

하나는 GetCharacterMovement()->bUseControllerDesiredRotation = true 를 통해 캐릭터를 부드럽게 카메라 방향으로 바꿔주는 것이었고,

다른 하나는 bUseControllerRotationYaw = true 를 통해 즉각적으로 캐릭터를 회전시키는 방법이었다

실험을 해본 결과, 루트모션이 적용된 몽타주는 실행 시 bUseControllerDesiredRotation 를 true 로 설정한다고 하더라도 그 순간 회전을 하지 않았다

그렇기에 몽타주를 실행할때는 bUseControllerRotationYaw = true 를 사용하고, 그렇지 않을때는 반대의 방법을 사용했다

이는 아래와 같은 로직을 통해 실행되었다

IFCharacter.cpp


void AIFCharacter::RotateToCamera()
{
	GetCharacterMovement()->bOrientRotationToMovement     = false;
	GetCharacterMovement()->bUseControllerDesiredRotation = true;
}

// needs the parameters to bind the delegate OnMontageStarted 
void AIFCharacter::RotateToCameraMontage(UAnimMontage* Montage)
{
	if (!AnimInstance->IsDrawOrSheatheMontage())
		bUseControllerRotationYaw = true;
}

void AIFCharacter::RotateDefault()
{
	GetCharacterMovement()->bOrientRotationToMovement     = true;
	GetCharacterMovement()->bUseControllerDesiredRotation = false;
}

// needs the parameters to bind the delegate OnMontageEnded
void AIFCharacter::RotateDefaultMontage(UAnimMontage* Montage, bool bInterrupted)
{
	bUseControllerRotationYaw = false;
	if (GetVelocity().Size() == 0)
	{
		GetCharacterMovement()->bOrientRotationToMovement     = true;
		GetCharacterMovement()->bUseControllerDesiredRotation = false;
	}
}

적용된 모습은 다음과 같다

자세를 취할때는 캐릭터가 카메라 방향으로 부드럽게 회전하고,

공격몽타주가 실행 중이더라도 캐릭터는 회전이 가능하다


다음주에 할 일

  • 일단 다음 스프린트 사이에 동원 훈련을 2박 3일 다녀와야 하기에,, 개발일지는 2주 뒤인 23일에 작성할 예정이다....
  • 무기의 추가와 공격을 완료했으니 이번 텀에는 드디어 도끼를 던져보고, 다시 돌아오게 하고자 한다
profile
토비폭스가 되고픈 게임 개발자

2개의 댓글

comment-user-thumbnail
2023년 4월 23일

k-토비폭스의 행보를 응원합니다

1개의 답글