이번에는 캐릭터 공격을 구현하였습니다.
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으로 넘어가는 방식으로 구현했습니다.