UE4 デバッグ表示についてのメモ


# 概要
UnrealEngine の文字列などのデバッグ表示のメモ書きです。


## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.24, 5.3.2

## 更新履歴
| 日付 | 内容 |
|:-----|:----|
|2020/03/28| 初版 |
|2024/09/02| ビューポートサイズの取得について追記|


## 参考
以下を参考にさせて頂きました、ありがとうございます。

[UE4:UEngine::AddOnScreenDebugMessage](https://docs.unrealengine.com/en-US/API/Runtime/Engine/Engine/UEngine/AddOnScreenDebugMessage/1/index.html)
[第0036回 / デバッグ表示を調査](https://ameblo.jp/ue4-master/entry-12532632697.html)
[[UE4] UDebugDrawService による2Dデバッグ描画 (C++)](https://qiita.com/jden/items/6d4af11ee7f9b6cda98c)
[UE4: 点や線を簡易的に3D空間内へ描画する方法、あるいは UKismetSystemLibrary::DrawDebug 系の紹介](https://usagi.hatenablog.jp/entry/2017/12/21/083000)


# 2D表示
スクリーンへの表示です。

## 2Dデバッグログ文字表示(C++)
画面左上に表示されます。
位置指定ができないので大量に出すと流れます。

以下、C++でのコード例。

```cpp:.cpp
FColor _Col = FColor::White;
FVector2D _Scl = FVector2D(3.0f, 3.0f);
GEngine->AddOnScreenDebugMessage(-1, 0.0f, _Col, FString::Printf(TEXT("Test!")), true, _Scl);

```

## 2Dデバッグログ文字表示(BP)

BPでは `Print String` や `Print Text` です。
引数文字の改行は `Shift + Enter` です。
![Print_BP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/a2c8788d-c2ba-31c8-6aa5-e3e366f0ad3b.jpeg)



## Canvasを使った表示(C++)
Canvas を使った2Dデバッグ文字表示で、表示位置を指定できます。
"Engine/Source/Runtime/Engine/Canvas.h"

コード例では、GameInstanceSubsystemを使ってフォント取得、デリゲートの登録/解除を行い、呼ばれる描画メソッドも持っています。

```cpp:MyGameInstanceSubsystem.h
UCLASS()
class TEST_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem
{
	GENERATED_BODY()
	
	UMyGameInstanceSubsystem();
	
public:
	// 初期化
	virtual void Initialize(FSubsystemCollectionBase& Collection);

	// 初期化解除
	virtual void Deinitialize();

	// 描画
	void Draw(UCanvas* InCanvas, APlayerController* InPC);


private:
	// 登録デリゲート
	FDelegateHandle			DrawDebugDelegate;

	// フォント
	UPROPERTY(Transient)
	class UFont*			FontObject;

};
```


```cpp:MyGameInstanceSubsystem.cpp

#include "MyGameInstanceSubsystem.h"
#include "Engine.h"

UMyGameInstanceSubsystem::UMyGameInstanceSubsystem()
{
	// フォント用意
	static ConstructorHelpers::FObjectFinder<UFont> font(TEXT("/Engine/EngineFonts/Roboto"));
	FontObject = font.Object;
}


// 初期化
void UMyGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
	// デリゲートを登録
	auto drawDebugDelegate = FDebugDrawDelegate::CreateUObject(this, &UMyGameInstanceSubsystem::Draw);
	
	if( drawDebugDelegate.IsBound() ){
		this->DrawDebugDelegate = UDebugDrawService::Register(TEXT("GameplayDebug"), drawDebugDelegate);
	}
}


// 初期化解除
void UMyGameInstanceSubsystem::Deinitialize()
{
	// デリゲート登録解除
	if( this->DrawDebugDelegate.IsValid() ){
		UDebugDrawService::Unregister(this->DrawDebugDelegate);
		this->DrawDebugDelegate.Reset();
	}
}

// 描画
void UMyGameInstanceSubsystem::Draw(UCanvas* InCanvas, APlayerController* InPC)
{
	if (!InCanvas || !InCanvas->Canvas){
		return;
	}

	// 文字描画１（DrawItemでの表示）
	FString _DispString;
	FVector2D _Pos = FVector2D(320.0f, 100.0f);
	FVector2D _Scl = FVector2D(3.0f, 3.0f);
	FLinearColor _Col = FLinearColor::Yellow;

	_DispString = FString::Printf(TEXT("test"));

	FCanvasTextItem _TextItem(_Pos, FText::FromString(_DispString), this->FontObject, _Col);
	_TextItem.Scale = _Scl;
	InCanvas->DrawItem(_TextItem);


	// 文字描画２（DrawTextでの表示）
	FVector2D _Pos2 = FVector2D(320.0f, 130.0f);
	FString _DispString2 = FString::Printf(TEXT("test2"));

	InCanvas->K2_DrawText(this->FontObject, _DispString2, _Pos2, _Scl, FLinearColor::Red);
}

```


実行すると画面中央付近に黄色文字と赤文字でテスト文字が3倍スケールで表示されます。
![sample_2Dfont.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/624136ac-c514-4943-31a3-ea522f1c17ef.jpeg)


## ビューポートサイズの取得について
ビューポートサイズの取得は `GEngine->GameViewport->GetViewportSize` で取得ができますが、Windowsのディスプレイ設定で拡大などしていた場合、そのままでは位置がズレてしまいます。


<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/66366a6d-cacf-b3d3-2257-9b513bc81561.png">


そのためDPIスケールを取得してビューポートサイズを再計算してあげる必要があります、以下コード例。

```cpp:.cpp
	// ビューポートのサイズを取得
	FVector2D _ViewportSize;
	GEngine->GameViewport->GetViewportSize(_ViewportSize);
		
	// DPIスケールを取得
	const float _DPIScale = GEngine->GameViewport->GetDPIScale();
	// DPIスケールを考慮したビューポートサイズを計算
	FVector2D _ScaledViewportSize = _ViewportSize / _DPIScale;

```

他に以下のように `FPlatformApplicationMisc`を使って拡大率を取得する方法もあるようです。

```cpp:
#include "HAL/PlatformApplicationMisc.h"
#include "Misc/Optional.h"

void GetCurrentDPIScale()
{
    // ウィンドウの中心座標を取得（例として(0, 0)）
    int32 _ScreenX = 0;
    int32 _ScreenY = 0;
    
    // DPI スケールを取得
    float _DPIScale = FPlatformApplicationMisc::GetDPIScaleFactorAtPoint(_ScreenX, _ScreenY);
}
```

:::note warn
`FPlatformApplicationMisc` を使うには Build.cs に "ApplicationCore" を追加する必要があることに注意。
:::



# 3D表示
3D世界への表示です。
アクターなどの任意のオブジェクトの情報を出す場合に使うと思います。

## Kismetライブラリでの表示
アクター位置など３D世界への文字表示ができます。
ソースは
"Engine/Source/Runtime/Engine/Class/Kismet/KismetSystemLibrary.h"
です。

以下コード例。

```cpp:.cpp
#include "Kismet/KismetSystemLibrary.h"

// アクター位置への表示
UKismetSystemLibrary::DrawDebugString(GetWorld(), GetActorLocation(), FString::Printf(TEXT("MyActor")), nullptr, FLinearColor::Black, 0);
```


文字以外にもラインやスフィアなどいろいろあります。

```cpp:KismetSystemLibrary.h
// ライン
UFUNCTION(BlueprintCallable, Category="Rendering|Debug", meta=(WorldContext="WorldContextObject", DevelopmentOnly))
static void DrawDebugLine(UObject* WorldContextObject, const FVector LineStart, const FVector LineEnd, FLinearColor LineColor, float Duration=0.f, float Thickness = 0.f);

// スフィア
UFUNCTION(BlueprintCallable, Category="Rendering|Debug", meta=(WorldContext="WorldContextObject", DevelopmentOnly))
static void DrawDebugSphere(UObject* WorldContextObject, const FVector Center, float Radius=100.f, int32 Segments=12, FLinearColor LineColor = FLinearColor::White, float Duration=0.f, float Thickness = 0.f);

// アロー
UFUNCTION(BlueprintCallable, Category="Rendering|Debug", meta=(WorldContext="WorldContextObject", DevelopmentOnly))
static void DrawDebugArrow(UObject* WorldContextObject, const FVector LineStart, const FVector LineEnd, float ArrowSize, FLinearColor LineColor, float Duration=0.f, float Thickness = 0.f);

```


BPだと `DrawDebugString` で3D世界へ文字表示ができます。
![DebugDrawString_BP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/6c1e7dd5-7b4d-2810-f195-19173576a9f9.jpeg)

文字以外もいろいろあります。
![Kismet_BP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/72c3c280-7fd3-3831-4035-2f0e839407ef.jpeg)



## DrawDebugHelpers での表示
Kismetライブラリと同様に3D世界への表示に使えます。
ソースは
"Engine/Source/Runtime/Engine/Public/DrawDebugHelpers.h"
です。

```cpp:DrawDebugHelpers.h
// 文字
void DrawDebugString(const UWorld* InWorld, FVector const& TextLocation, const FString& Text, class AActor* TestBaseActor = NULL, FColor const& TextColor = FColor::White, float Duration = -1.000000, bool bDrawShadow = false, float FontScale = 1.f);

// ライン
void DrawDebugLine(const UWorld* InWorld, FVector const& LineStart, FVector const& LineEnd, FColor const& Color, bool bPersistentLines = false, float LifeTime=-1.f, uint8 DepthPriority = 0, float Thickness = 0.f);

// ボックス
void DrawDebugBox(const UWorld* InWorld, FVector const& Center, FVector const& Extent, FColor const& Color, bool bPersistentLines = false, float LifeTime=-1.f, uint8 DepthPriority = 0, float Thickness = 0.f);
```


# まとめ
UMG以外のデバッグ表示をまとめました。
スクリーン座標への2Dデバッグ文字表示の実装がやや面倒です。