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으로 카테고리별 디버그 드로잉을 제어하세요.