언리얼 엔진

Unreal Character - 캐릭터 공격 판정 트러블슈팅 정리

로안님 2025. 5. 29. 17:56

UE5 공격 판정 트러블슈팅 정리

🎯 목표

  • 바닥을 공격해도 공격이 취소되지 않아야 합니다.
  • 스폰된 엑터(예: 스포너, 몬스터, 벽 등)가 겹쳐 있을 경우에도 모든 충돌 대상을 감지하고 올바르게 판단해야 합니다.

🧱 문제 1: 바닥 공격 무시 조건이 있음에도 공격이 취소되는 현상

🔎 현상

  • Hit.ImpactNormal.Z > 0.8f 조건으로 바닥을 감지하면 무시하도록 했지만,
  • UE_LOG(LogTemp, Warning, TEXT("바닥 무시: StaticMeshActor_1")); 로그 이후에도
  • "공격 취소" 로그가 출력되며 CancelAttack()이 호출됨.

🧨 원인 분석

  • 한 번 continue로 무시된 같은 바닥 액터가 이후 로직에서 다시 감지됨.
  • CanBeCut() 또는 인터페이스가 없는 경우 else 문으로 넘어가 공격이 취소됨.
  • → 한 프레임 내에 동일 액터가 여러 번 감지될 수 있다는 것을 의미함.

🛠 해결 방법

  • TSet<AActor*> IgnoredActors를 사용해 한 틱 내 이미 무시된 액터는 다시 무시되도록 처리
  • IgnoredActors.Add(HitActor) 후 continue
  • 중복 감지 여부를 확인하기 위한 로그 추가
if (Hit.ImpactNormal.Z > 0.8f)
{
    UE_LOG(LogTemp, Warning, TEXT("[Trace] 바닥 무시: %s"), *GetNameSafe(HitActor));
    IgnoredActors.Add(HitActor);
    continue;
}

🧱 문제 2: 여러 엑터가 겹쳐 있을 때, 한 개만 감지되고 나머지는 무시되는 현상

🔎 현상

  • 몬스터가 스포너와 겹쳐 있을 때 LineTraceSingleByChannel 또는 LineTraceMultiByChannel으로 스포너만 감지됨
  • 벽이나 다른 엑터는 감지되지 않음
  • 라인트레이스는 처음 충돌한 엑터만 반환하므로 의도한 동작이 아님

🧨 원인 분석

  • LineTrace는 언리얼 엔진에서 가장 기본적인 충돌 감지 방식으로, 한 지점에서 직선 방향으로 쏘는 광선(Ray) 을 기반으로 작동합니다. 이 방식은 가장 먼저 충돌하는 액터 하나만 감지하기 때문에 성능은 뛰어나지만, 겹쳐 있는 액터의 뒷면까지 확인하지 못하는 한계가 있습니다. 이로 인해 예를 들어 얇은 벽 뒤에 있는 몬스터가 감지되지 않고 벽만 감지되는 현상이 발생할 수 있습니다. 예를 들어 얇은 벽 뒤에 몬스터가 겹쳐 있는 경우, 벽만 감지되고 몬스터는 감지되지 않아 공격 대상에서 누락될 수 있습니다.
  • LineTraceMultiByChannel도 여러 액터를 반환하긴 하지만, 같은 위치에 겹쳐 있는 경우엔 감지가 누락되거나 불안정할 수 있어 실전에서 겹침 판정에는 적합하지 않습니다.
  • → 근접 범위 판정에는 Sweep이 더 적합함

🛠 해결 방법

  • SweepMultiByChannel로 판정 로직 교체
  • FCollisionShape::MakeSphere() 또는 MakeCapsule() 사용하여 무기 궤적 기반 판정 가능
  • 매 스텝마다 다수 엑터 감지 가능
FCollisionShape SweepShape = FCollisionShape::MakeSphere(SphereRadius);
if (World->SweepMultiByChannel(HitResults, Start, End, FQuat::Identity, ECC_SwordTrace, SweepShape, Params))
{
    for (const FHitResult& Hit : HitResults)
    {
        // 처리 로직
    }
}

🧪 디버그 시각화

DrawDebugCapsule(World, Start, Radius, Radius, FQuat::Identity, FColor::Blue, false, 1.0f);

🔍 디버깅 도구 활용

  • UE_LOG로 HitActor->GetName(), ImpactNormal, Sweep 충돌 좌표 출력
  • IgnoredActors 캐시를 프레임마다 로그로 검증

✍️ 마무리

이번 트러블슈팅을 통해 한 프레임 내 중복 감지와 라인트레이스 한계를 해결할 수 있었습니다.
언리얼 엔진의 충돌 감지 방식(Raycast vs Sweep)의 차이를 이해하고 적절히 사용하는 것이 중요합니다.

Sweep 방식은 겹쳐 있는 다수 엑터를 안정적으로 감지할 수 있는 장점이 있지만, 연산 비용이 증가할 수 있고, 때때로 의도하지 않은 충돌(Fake Hit, False Positive) 이 발생할 수 있습니다. 따라서 범위, 빈도, 충돌 채널 설계에 대한 고민이 함께 필요합니다.