언리얼엔진5 공부

TIL: 언리얼 엔진 5 C++ 기반 막기 & 패링 시스템 구현

Client Side 2026. 1. 21. 22:17

1. 핵심 개념 및 설계

단순히 애니메이션을 재생하는 것이 아니라, 캐릭터의 상태(State)를 정의하고 공격 판정이 들어왔을 때 이를 어떻게 처리할지가 핵심입니다.

  • 막기(Blocking): 공격 대미지를 일정 비율 감소시키거나 무효화함.
  • 패링(Parrying): 공격이 적중하기 직전 특정 프레임에 막기를 성공했을 때, 공격자를 경직(Stun) 상태로 만들고 반격 기회를 얻음.

2. 주요 코드 구현 (Senior Programmer 스타일)

A. 상태 정의 및 변수 설정 (MyCharacter.h)

bool 변수 하나로 관리하기보다 UPROPERTY를 통해 에디터에서 제어 가능하게 설계합니다.

// ECharacterState 등의 열거형으로 상태를 관리하는 것이 유지보수에 유리함
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat", meta = (AllowPrivateAccess = "true"))
bool bIsBlocking;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Combat", meta = (AllowPrivateAccess = "true"))
bool bIsParrying;

// 패링 유효 시간 (초 단위)
UPROPERTY(EditAnywhere, Category = "Combat")
float ParryingWindow = 0.2f;

FTimerHandle ParryingTimerHandle;

 

B. 로직 구현 (MyCharacter.cpp)

Tick을 사용하지 않고 Timer를 사용하여 패링 판정 시간을 관리합니다.

 

void AMyCharacter::StartBlock()
{
    bIsBlocking = true;
    bIsParrying = true;

    // 패링 유효 프레임 설정 (Tick 최소화)
    GetWorldTimerManager().SetTimer(ParryingTimerHandle, this, &AMyCharacter::EndParryingWindow, ParryingWindow, false);
    
    // 막기 애니메이션 몽타주 재생 로직 추가
}

void AMyCharacter::EndParryingWindow()
{
    bIsParrying = false;
}

void AMyCharacter::EndBlock()
{
    bIsBlocking = false;
    bIsParrying = false;
    GetWorldTimerManager().ClearTimer(ParryingTimerHandle);
}

 

C. 대미지 판정 로직 (TakeDamage 오버라이드)

피격 시점에서 상태를 체크합니다. Cast를 사용할 때는 반드시 방어 코드를 작성합니다.

 

float AMyCharacter::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
    if (bIsParrying)
    {
        // 패링 성공: 대미지 0 및 공격자 경직 처리
        TriggerParryingSuccess(DamageCauser);
        return 0.f;
    }

    if (bIsBlocking)
    {
        // 막기 성공: 대미지 감소 (예: 20%만 받음)
        return Super::TakeDamage(DamageAmount * 0.2f, DamageEvent, EventInstigator, DamageCauser);
    }

    return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
}