PART 10 - 강의 5/6

DrawDebug 활용

런타임 시각화, 디버그 드로잉 함수, 게임플레이 디버깅

01

DrawDebug 함수 기초

월드에 디버그 도형을 직접 그리는 방법

기본 개념

DrawDebug 함수들은 게임 실행 중 3D 공간에 도형, 선, 텍스트를 그려서 디버깅을 돕습니다. Visual Logger와 달리 실시간으로 화면에 직접 표시됩니다.

Include Header #include "DrawDebugHelpers.h"

공통 파라미터

파라미터 타입 설명
World UWorld* 그릴 월드 (GetWorld())
bPersistentLines bool true면 수동 삭제 전까지 유지
LifeTime float 표시 시간 (초), -1이면 1프레임
DepthPriority uint8 깊이 우선순위
Thickness float 선 두께
02

기본 도형 그리기

점, 선, 박스, 구 등 기본 도형

점과 선

Points and Lines // 점 (작은 구) DrawDebugPoint( GetWorld(), Location, // FVector 10.0f, // 크기 FColor::Red, false, // bPersistentLines 5.0f // LifeTime ); // 선 DrawDebugLine( GetWorld(), StartLocation, EndLocation, FColor::Green, false, 5.0f, 0, // DepthPriority 2.0f // Thickness ); // 화살표 DrawDebugDirectionalArrow( GetWorld(), StartLocation, EndLocation, 50.0f, // 화살표 크기 FColor::Blue, false, 5.0f, 0, 3.0f );

박스와 구

Boxes and Spheres // 박스 DrawDebugBox( GetWorld(), Center, // 중심점 FVector(50, 50, 100), // 반 크기 (Half Extent) FColor::Yellow, false, 5.0f ); // 회전된 박스 DrawDebugBox( GetWorld(), Center, FVector(50, 50, 100), FQuat(GetActorRotation()), // 회전 FColor::Orange, false, 5.0f ); // 구 DrawDebugSphere( GetWorld(), Center, 100.0f, // 반지름 16, // 세그먼트 수 FColor::Cyan, false, 5.0f ); // 캡슐 DrawDebugCapsule( GetWorld(), Center, 100.0f, // Half Height 50.0f, // Radius FQuat::Identity, FColor::Purple, false, 5.0f ); // 원통 DrawDebugCylinder( GetWorld(), BottomCenter, TopCenter, 50.0f, // Radius 16, // Segments FColor::White, false, 5.0f );

원과 좌표축

Circles and Axes // 원 DrawDebugCircle( GetWorld(), Center, 100.0f, // Radius 32, // Segments FColor::Green, false, 5.0f, 0, 2.0f, FVector::UpVector, // Y축 (원의 평면) FVector::ForwardVector, // Z축 false // bDrawAxis ); // 좌표축 DrawDebugCoordinateSystem( GetWorld(), Location, FRotator::ZeroRotator, 100.0f, // Scale false, 5.0f ); // 원뿔 (시야각 표시 등) DrawDebugCone( GetWorld(), Origin, Direction, // 방향 벡터 300.0f, // 길이 FMath::DegreesToRadians(30.0f), // 각도 FMath::DegreesToRadians(30.0f), // 각도 16, // Sides FColor::Yellow, false, 5.0f );
03

텍스트와 문자열 그리기

월드 공간에 디버그 텍스트 표시

월드 공간 텍스트

World Space Text // 3D 공간에 텍스트 DrawDebugString( GetWorld(), Location, TEXT("Debug Text"), nullptr, // TestBaseActor (null이면 위치 고정) FColor::White, 5.0f, // Duration true, // bDrawShadow 1.0f // FontScale ); // 액터를 따라다니는 텍스트 DrawDebugString( GetWorld(), FVector(0, 0, 100), // 오프셋 FString::Printf(TEXT("HP: %.0f"), Health), this, // 따라다닐 액터 FColor::Green, 0.0f, // Duration (0 = 1프레임) true ); // 상태 정보 표시 void AMyCharacter::DrawDebugInfo() { FVector HeadLocation = GetActorLocation() + FVector(0, 0, 150); DrawDebugString( GetWorld(), HeadLocation, FString::Printf(TEXT("State: %s\nHP: %.0f/%.0f\nTarget: %s"), *UEnum::GetValueAsString(CurrentState), CurrentHealth, MaxHealth, *GetNameSafe(CurrentTarget)), nullptr, FColor::Yellow, 0.0f, true, 1.5f ); }
04

실전 디버깅 예제

게임플레이 시스템 디버깅에 활용

충돌 디버깅

Collision Debugging void AMyActor::PerformSweepAttack() { FVector Start = GetActorLocation(); FVector End = Start + GetActorForwardVector() * 300.0f; float Radius = 100.0f; FCollisionQueryParams QueryParams; QueryParams.AddIgnoredActor(this); TArray<FHitResult> Hits; bool bHit = GetWorld()->SweepMultiByChannel( Hits, Start, End, FQuat::Identity, ECC_Pawn, FCollisionShape::MakeSphere(Radius), QueryParams ); #if ENABLE_DRAW_DEBUG // 스윕 경로 시각화 DrawDebugCapsule( GetWorld(), (Start + End) / 2, FVector::Distance(Start, End) / 2, Radius, FQuat::FindBetweenVectors(FVector::UpVector, (End - Start).GetSafeNormal()), bHit ? FColor::Red : FColor::Green, false, 2.0f ); // 히트 포인트 표시 for (const FHitResult& Hit : Hits) { DrawDebugSphere( GetWorld(), Hit.ImpactPoint, 15.0f, 8, FColor::Red, false, 2.0f ); DrawDebugString( GetWorld(), Hit.ImpactPoint + FVector(0, 0, 30), FString::Printf(TEXT("Hit: %s"), *Hit.GetActor()->GetName()), nullptr, FColor::White, 2.0f ); } #endif }

AI 시야 디버깅

AI Vision Debugging void AMyAIController::DrawVisionDebug() { #if ENABLE_DRAW_DEBUG APawn* ControlledPawn = GetPawn(); if (!ControlledPawn) return; FVector EyeLocation = ControlledPawn->GetActorLocation() + FVector(0, 0, 80); FVector ForwardDir = ControlledPawn->GetActorForwardVector(); // 시야 범위 (부채꼴) const int32 NumSegments = 24; const float VisionAngle = 60.0f; const float VisionRange = 1000.0f; for (int32 i = 0; i < NumSegments; ++i) { float AngleDeg = -VisionAngle + (VisionAngle * 2 * i / (NumSegments - 1)); FVector Dir = ForwardDir.RotateAngleAxis(AngleDeg, FVector::UpVector); FVector EndPoint = EyeLocation + Dir * VisionRange; DrawDebugLine( GetWorld(), EyeLocation, EndPoint, FColor(100, 255, 100, 128), false, 0.0f, 0, 1.0f ); } // 시야 원호 DrawDebugCircle( GetWorld(), EyeLocation, VisionRange, 32, FColor::Green, false, 0.0f, 0, 2.0f, FVector::ForwardVector, FVector::RightVector, false ); // 현재 타겟 표시 if (CurrentTarget) { DrawDebugLine( GetWorld(), EyeLocation, CurrentTarget->GetActorLocation(), FColor::Red, false, 0.0f, 0, 3.0f ); DrawDebugSphere( GetWorld(), CurrentTarget->GetActorLocation(), 50.0f, 12, FColor::Red, false, 0.0f ); } #endif }

경로 시각화

Path Visualization void AMyAIController::DrawPathDebug() { #if ENABLE_DRAW_DEBUG UPathFollowingComponent* PathComp = GetPathFollowingComponent(); if (!PathComp) return; FNavPathSharedPtr Path = PathComp->GetPath(); if (!Path.IsValid()) return; const TArray<FNavPathPoint>& Points = Path->GetPathPoints(); for (int32 i = 0; i < Points.Num(); ++i) { // 경로 점 DrawDebugSphere( GetWorld(), Points[i].Location, 20.0f, 8, i == 0 ? FColor::Green : (i == Points.Num() - 1 ? FColor::Red : FColor::Blue), false, 0.0f ); // 경로 선 if (i < Points.Num() - 1) { DrawDebugLine( GetWorld(), Points[i].Location, Points[i + 1].Location, FColor::Cyan, false, 0.0f, 0, 3.0f ); } // 인덱스 표시 DrawDebugString( GetWorld(), Points[i].Location + FVector(0, 0, 30), FString::Printf(TEXT("%d"), i), nullptr, FColor::White, 0.0f ); } #endif }
05

조건부 컴파일과 성능

Shipping 빌드에서 디버그 드로잉 제외

조건부 매크로

Conditional Compilation // ENABLE_DRAW_DEBUG는 Shipping 빌드에서 0 #if ENABLE_DRAW_DEBUG DrawDebugSphere(GetWorld(), Location, 50.0f, 12, FColor::Red); #endif // 커스텀 매크로 정의 #if ENABLE_DRAW_DEBUG #define DRAW_DEBUG_SPHERE(World, Center, Radius, Color) \ DrawDebugSphere(World, Center, Radius, 12, Color, false, 0.0f) #define DRAW_DEBUG_LINE(World, Start, End, Color) \ DrawDebugLine(World, Start, End, Color, false, 0.0f) #define DRAW_DEBUG_STRING(World, Location, Text) \ DrawDebugString(World, Location, Text, nullptr, FColor::White, 0.0f) #else #define DRAW_DEBUG_SPHERE(World, Center, Radius, Color) #define DRAW_DEBUG_LINE(World, Start, End, Color) #define DRAW_DEBUG_STRING(World, Location, Text) #endif // 사용 DRAW_DEBUG_SPHERE(GetWorld(), GetActorLocation(), 100.0f, FColor::Green); DRAW_DEBUG_LINE(GetWorld(), Start, End, FColor::Red);

토글 가능한 디버그 시스템

Toggleable Debug // 디버그 드로잉 매니저 UCLASS() class UDebugDrawSubsystem : public UWorldSubsystem { GENERATED_BODY() public: UPROPERTY(BlueprintReadWrite) bool bDrawAIDebug = false; UPROPERTY(BlueprintReadWrite) bool bDrawCollisionDebug = false; UPROPERTY(BlueprintReadWrite) bool bDrawPathDebug = false; }; // 사용 예 void AMyAIController::Tick(float DeltaTime) { Super::Tick(DeltaTime); #if ENABLE_DRAW_DEBUG if (UDebugDrawSubsystem* DebugSS = GetWorld()->GetSubsystem<UDebugDrawSubsystem>()) { if (DebugSS->bDrawAIDebug) { DrawVisionDebug(); } if (DebugSS->bDrawPathDebug) { DrawPathDebug(); } } #endif } // 콘솔 명령 등록 static FAutoConsoleCommand CmdToggleAIDebug( TEXT("Debug.AI"), TEXT("Toggle AI debug drawing"), FConsoleCommandWithWorldDelegate::CreateLambda([](UWorld* World) { if (UDebugDrawSubsystem* SS = World->GetSubsystem<UDebugDrawSubsystem>()) { SS->bDrawAIDebug = !SS->bDrawAIDebug; } }) );
성능 팁
  • Tick에서 DrawDebug는 매 프레임 호출되므로 필요할 때만 사용
  • LifeTime을 적절히 설정하여 불필요한 그리기 방지
  • ENABLE_DRAW_DEBUG 매크로로 Shipping 빌드에서 제외
  • 복잡한 도형은 세그먼트 수를 줄여서 성능 최적화
SUMMARY

핵심 요약

  • DrawDebugHelpers.h를 include하여 디버그 드로잉 함수 사용
  • DrawDebugLine, DrawDebugSphere, DrawDebugBox 등 기본 도형 제공
  • DrawDebugString으로 3D 공간에 텍스트 표시
  • 충돌, AI 시야, 경로 등 게임플레이 시스템 디버깅에 활용
  • ENABLE_DRAW_DEBUG 매크로로 Shipping 빌드에서 제외
다음 강의 예고

다음 강의에서는 memreport, LLM, obj list 등 메모리 프로파일링 도구를 학습합니다.

PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: 기본 DrawDebug 함수 활용

DrawDebugSphere()로 적 감지 범위, DrawDebugLine()으로 AI 시선 방향, DrawDebugBox()로 히트박스를 시각화하세요. bPersistentLines와 LifeTime 파라미터를 조정하세요.

실습 2: RPG 전투 디버그 시각화

DrawDebugCapsule()로 캐릭터 충돌체, DrawDebugDirectionalArrow()로 공격 방향, DrawDebugString()으로 데미지 수치를 실시간 표시하세요. #if !UE_BUILD_SHIPPING으로 감싸세요.

심화 과제: 인터랙티브 디버그 시스템

콘솔 명령(Exec)으로 토글 가능한 디버그 시각화 시스템을 구현하세요. rpg.debug.combat, rpg.debug.ai, rpg.debug.navigation으로 카테고리별 디버그 드로잉을 제어하세요.