[UE5] 전투 시스템, 캐릭터 전면 개편 (프로젝트ASR - 개발일지7)
이전 포스팅 이후 전투 이외에도 많은 시스템이 개발 중이지만 전부 한 포스팅에 담기에는 내용이 많아 전투 시스템과 캐릭터를 전면 개편하였던 업데이트를 기준으로 포스팅을 작성합니다.
[전투 시스템 개편 후 보스 전투 테스트 영상 (클래스 2개)]
전투 시스템 전면 개편
이전 포스팅에서, 전투 시스템이 확정되었고 3개의 캐릭터에서 모두 동일한 스펙으로 개발을 마쳤다.
약공격, 강공격, 가드, 패리, 회피, 긴급회피, 스킬1, 스킬2, 궁극기(AOE or 버프)를 3개의 캐릭터에 애니메이션과 VFX, SFX 모두 세팅하니 약 1주 이상이 지났고 이후 다시 전투 시스템을 점검하였다.
처음 보스를 만들고 3개의 캐릭터로 각각 보스를 공략하고 클리어할 때까지는 만족스러웠다. 확연히 다른 전투스타일을 가진 3개의 캐릭터(카타나, 대검, 총기)를 번갈아 가며 플레이하는 것도 재미있었다.
하지만 개발된 보스의 경직 시스템과 현재 캐릭터들의 전투/콤보 시스템의 합이 맞지 않았다.
아래 이전 보스 전투 플레이 Gif와 같이 회피 이후, 공격을 2~3번 하는 패턴이 게임 끝날 때까지 반복된다.
개발 중에 이를 우려하고 있었고 그래서 오토가드, 가드리벤지로 이어지는 가드 + 스태미나 시스템을 고안하고 구현하였다. 플레이어가 딜레이 상태인 적을 연속으로 공격하며 적의 스태미나를 감소시키는 시스템으로 숙련된 플레이어는 공격을 이어가다가 적의 카운터를 회피하고 대미지를 누적시키도록 하였다.
하지만 두 가지 문제를 발견하였다.
적의 스태미나를 감소시키려면 적이 공격을 마치고 다음 공격을 준비할 때까지 타격을 가해야 하는데 플레이어의 콤보 시스템은 약공격 또는 강공격을 연타하는 것이 전부인 것이다. '회피 후 공격 연타' 패턴이 굳어질 수밖에 없으며 공격 간 딜레이가 긴 공격 패턴은 사용할 필요가 없어 약공격을 연타하여야 스태미나를 깎는 것이 유일한 선택지가 되었다.
다음으로 보스의 스태미나를 모두 소진시킨 뒤에는 보스의 공격을 패리하면 보스는 큰 대미지를 입으며 뒤로 밀리는데, 이 또한 숙련 플레이어는 패리 / 초심자는 마찬가지로 회피 후 공격 연타가 유일한 선택지가 된다.
직접 플레이하며 수십 차례 보스를 쓰러트려 익숙해진 이후에도 회피 -> 공격으로 스태미나를 모두 깎아 가드 불능상태로 만들고 패리를 반복하는 것이 전부였다. 이후 화려한 보스나 다양한 캐릭터와 무기를 추가하더라도 ARPG의 핵심인 전투가 단순하고 재미없다면 플레이어는 금방 게임에 대한 흥미를 잃을 것이라고 생각했다.
이후 전투 시스템을 다시 생각해보고 게임의 방향성을 정해야겠다는 생각이 들어 다양한 게임의 전투 시스템에 대해 기록하고 참고하였다. 다른 게임과 비교해 보니 현재 전투는 ‘여러 정보를 종합한 플레이어의 순간적인 판단과 선택 그리고 그에 따른 보상’을 플레이어에게 전혀 제공하지 않고 있다는 것을 깨닫게 되었다.
콤보 진행도, 보스의 스태미나, 보스의 체력, 플레이어의 체력, 플레이어의 스태미나, 보스의 공격 패턴 등에 따라 플레이어가 다른 선택을 내릴 수 있도록 하는 것을 목표로 전투 시스템 개편을 시작했다.
콤보 시스템 확장
약공격, 강공격의 입력에 따라 애니메이션 몽타주를 저장한 배열에서 Index를 증가시키며 애니메이션 시퀀스를 선택하던 기존의 시스템 대신 약공격, 강공격을 정해진 콤보에 따라 입력하면 새로운 패턴의 공격이 가능하도록 개편하였다.
// Normal Attack Combo - Deprecated
if (NormalAttackMontages.IsValidIndex(AttackIndex) && NormalAttackMontages[AttackIndex] != nullptr)
{
SetCombatState(ECombatState::ECS_Attack);
PlayAnimMontage(NormalAttackMontages[AttackIndex]);
if (NormalAttackIndex + 1 >= NormalAttackMontages.Num())
{
NormalAttackIndex = 0;
}
else
{
++NormalAttackIndex;
}
}
위 이전 코드와 같이 AttackIndex와 배열을 사용하여 애니메이션을 선형적으로 재생하는 대신 애니메이션 마다 현재 플레이어의 누적 콤보에 따라 새로운 애니메이션을 선택하도록 하였다.
이제 플레이어는 콤보에 있어서 다양한 선택지가 생겼다.
하지만 새로운 콤보들이 진짜 선택지가 되려면 선택할 이유가 있어야 한다.
새로운 공격 타입 추가하고 경직 시스템을 개편하여 이유를 부여하였다.
공격 타입 추가, 경직 시스템 개편
우선 일반 공격보다 상위에 있는 특수한 공격 타입인 Lethal, Fatal Attack을 추가하였다.
Lethal Attack은 보스의 자세를 무너뜨릴 수 있는 공격으로 보스는 공격받으면 피격 애니메이션이 바로 재생되며 가드 하면 스태미나가 크게 감소한다. 보스에게도 Lethal Attack을 추가하여 플레이어의 스태미나 관리 난이도를 올렸다.
Fatal Attack은 '가드 불가능 기술'로 가장 판정 우선도가 높은 공격으로 높은 대미지를 가지고 있다. 마찬가지로 보스도 Fatal Attack을 사용하며 플레이어는 이를 가드 할 수 없다.
이제 플레이어는 보스의 공격 도중에도 회피, 가드이외에 다른 선택지가 생겼다. 바로 적의 자세를 무너뜨리며 공격을 끊어버리는 Lethal, Fatal Attack이 포함된 콤보를 입력하는 것이다.
특정 콤보가 항상 최고의 선택지가 되지 않도록 Fatal Attack 같은 강력한 공격은 가장 길고 느린 콤보의 끝에 배치하였으며 일반 공격 콤보를 제외한 콤보 공격은 모두 스태미나를 소모하도록 하였다.
직접 정의한 공격 정보 구조체에 Lethal, Fatal Attack 여부(이후 Enum으로 변경 예정)를 나타내는 필드를 추가하였다.
이미 전투 인터페이스의 피격 판정 함수에서 위 구조체를 매개변수로 받고 있기 때문에 피격 애니메이션 처리 함수에서 분기처리를 해주는 것으로 구현은 간단히 끝났다.
보스가 공격준비를 하고 있을 때, 플레이어는 이제 아래 항목을 고려하여 다음 입력을 선택한다.
- 타격 판정 까지의 시간
- 현재 자신의 스태미나
- 현재 진행중인 콤보
- 보스의 공격 타입(일반, Lethal, Fatal)
- 보스의 스태미나, 체력
보스의 공격 타격 판정까지 시간 내에 현재 공격 애니메이션에서 Fatal Attack이 포함된 콤보로 연계할 수 있고 스태미나가 충분하다는 판단을 할 수 있는 숙련된 플레이어는 아래 Gif처럼 공격적인 플레이가 가능하다.
뒤로 짧게 회피하고나서 파란 검기와 함께 앞으로 크게 회전하며 베는 보스의 패턴을 숙지한 플레이어(본인)는 적이 공격 사거리에 들 것을 예측하여 이런 플레이도 가능하다.
보스의 Lethal Attack, Fatal Attack에 플레이어는 회피를 하는 것이 정답이다. 더 재미있는 전투를 위해 하이리스크 하이리턴의 카운터 공격을 추가하였다. Lethal Attack은 정확한 타이밍(0.1s)에 가드 하여 패리 하면 카운터 공격으로 연계가 가능하며 Fatal Attack은 정확한 타이밍에 회피하면 카운터 공격으로 연계된다.
스태미나 시스템 수정
스태미나 시스템도 플레이하면서 전반적으로 수정하였다.
- 공격, 회피, 가드 도중 스태미나 자연 회복 X
- 적의 공격으로 스태미나 소진시 플레이어도 보스처럼 큰 경직에 빠짐
- 회피, 가드 스태미나 소모량 조정
- 패리 성공 시 플레이어 스태미나 회복
- 스태미나를 모두 소진하면 일정시간 자연 회복 X
적과 붙어서 전투를 계속 이어가려면 스태미나 회복 수단인 패리를 성공시켜야 하며 보스의 Lethal Attack과 연속 공격 패턴으로 스태미나가 소진되어 결국 전투를 잠시 쉬도록 전투의 템포를 조절하였다.
무리하게 전투를 이어가다 보스의 Lethal Attack과 회피로 스태미나가 바닥나게 되었고 보스의 공격을 가드 하면 아래처럼 가드브레이크 경직에 빠진다. 스태미나는 모두 소진하게 되면 약 1.5초가량 스태미나 회복이 불가능해 보스 연속공격 패턴이 나왔으면 바로 큰 대미지를 받게 되었을 것이다.
더 큰 개편이 필요한 것은 보스의 스태미나 시스템이었다.
원래 시스템을 유지하면 스태미나 소진 이후에는 여전히 계속 패리만 반복하는 것이 유일한 선택지가 되어버린다.
경직 매커니즘을 유지하면서 스태미나 소진이 유의미한 베네핏을 주도록 하기 위해 대미지 배율 계수를 추가하였다. 이전에 방어력 감소, 공격력 증가 등을 염두에 두고 1.0 고정 값으로 만들어둔 대미지 계수를 활용하였다. 스태미나를 모두 소진시키면 경직에 빠지면서 받는 대미지 계수가 0.5씩 증가하도록 설정하였다.
// BossEnemy.cpp
void ABossEnemy::GuardBroken()
{
DamageMultiplier += 0.5f;
if (BossInfoWidget != nullptr)
{
BossInfoWidget->UpdateDamageMultiPlier();
}
OnStaminaChanged.Broadcast();
SetInvulnerable(true);
Super::GuardBroken();
FTimerHandle TimerHandle;
GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &ABossEnemy::RefillStamina, 0.5f, false);
}
BossEnemy 클래스는 BaseEnemy 클래스에서 파생되었기 때문에 아래와 같이 기능을 담당하는 클래스를 나누었다
- 피격 애니메이션, 상태 관리는 BaseEnemy 클래스에서 담당
- 스태미나 Delegate Broadcast(스태미나 0이 되었을 때 UI 변경을 위해), 무적 상태 부여, 스태미나 리필 등 보스에게만 추가되는 로직은 BossEnemy 클래스에서 담당
- OnStaminaChanged에 바인드 된 보스 UI 클래스에서는 스태미나가 0이 되면서 대미지 계수 색상, 스태미나 바 색상을 빨간색으로 일정 시간 동안 변경하여 플레이어가 이를 인지할 수 있도록 하였다.