캐릭터 공격

최기승·2024년 3월 3일
0

캐릭터 공격


이번에는 캐릭터 공격을 구현하였습니다.
Combo를 추가하였으며 JumpSection으로 구현하였습니다.


공격 모션 몽타주

다음과 같이 Section을 나누었으며 ComboCount가 증가할 경우 다음 Section으로 이동하는 방식으로 구현했습니다.


void ASLPlayerCharacter::Attack()
{
	ProcessComboCommand();
}

void ASLPlayerCharacter::ProcessComboCommand()
{
	if (CurrentCombo == 0)
	{
		ComboActionBegin();
		return;
	}

	if (!ComboTimerHandle.IsValid())
	{
		HasNextComboCommand = false;
	}
	else
	{
		HasNextComboCommand = true;
	}
}

void ASLPlayerCharacter::ComboActionBegin()
{
	// Combo Status
	CurrentCombo = 1;

	// Movement Setting
	GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_None);

	// Animation Setting
	const float AttackSpeedRate = 1.0f;
	UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
	AnimInstance->Montage_Play(ComboActionMontage, AttackSpeedRate);

	FOnMontageEnded EndDelegate;
	EndDelegate.BindUObject(this, &ASLPlayerCharacter::ComboActionEnd);
	AnimInstance->Montage_SetEndDelegate(EndDelegate, ComboActionMontage);

	ComboTimerHandle.Invalidate();
	SetComboCheckTimer();
}

Attack함수가 실행되면 ComboCommand가 작동되며 콤보 공격을 시작합니다.
시작 콤보는 1로 주어지며 ComboActionEnd를 EndDelegate에 바인드했습니다.


콤보 공격


void ASLPlayerCharacter::ComboActionEnd(UAnimMontage* TargetMontage, bool IsProperlyEnded)
{
	ensure(CurrentCombo != 0);
	CurrentCombo = 0;
	GetCharacterMovement()->SetMovementMode(EMovementMode::MOVE_Walking);
}

void ASLPlayerCharacter::SetComboCheckTimer()
{
	int32 ComboIndex = CurrentCombo - 1;
	ensure(ComboActionData->EffectiveFrameCount.IsValidIndex(ComboIndex));

	const float AttackSpeedRate = 1.0f;
	float ComboEffectiveTime = (ComboActionData->EffectiveFrameCount[ComboIndex] / ComboActionData->FrameRate) / AttackSpeedRate;
	if (ComboEffectiveTime > 0.0f)
	{
		GetWorld()->GetTimerManager().SetTimer(ComboTimerHandle, this, &ASLPlayerCharacter::ComboCheck, ComboEffectiveTime, false);
	}
}

void ASLPlayerCharacter::ComboCheck()
{
	ComboTimerHandle.Invalidate();
	if (HasNextComboCommand)
	{
		UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();

		CurrentCombo = FMath::Clamp(CurrentCombo + 1, 1, ComboActionData->MaxComboCount);
		FName NextSection = *FString::Printf(TEXT("%s%d"), *ComboActionData->MontageSectionNamePrefix, CurrentCombo);
		AnimInstance->Montage_JumpToSection(NextSection, ComboActionMontage);
		SetComboCheckTimer();
		HasNextComboCommand = false;
	}
}

엔진에서 만들어 둔 ComboActionData를 사용하여 저장된 MaxComboCount와 MontageSectionName을 가져와 주어진 시간 동안 공격이 호출되었다면 NextSection으로 넘어가는 방식으로 구현했습니다.

profile
발전하는 개발자를 꿈꾸는 프로그래머

0개의 댓글

관련 채용 정보