[UE4] デバッグに関するTips

UE4でデバッグをする際に役に立つTipsを紹介します。
主にUE4とVisualStudioに関する内容となっています。

# ログ
## コールスタックをログに出力する
このコードを追加すると好きなタイミングでコールスタックをログに出力します。
初回出力時のみヒッチがありますが、仕組み自体はAssert時と同じです。
複数呼ばれる処理、デバッガを差しながらだと分かりにくい処理のデバッグに便利です。
パッケージ時は`Include Debug Files`を有効にする必要があります。

```cpp:
#if !NO_LOGGING // Test/Shippingはログ出力しないため任意
	FDebug::DumpStackTraceToLog();
#endif

	// UE4.26とかはVerbosityを指定する引数が必要
	FDebug::DumpStackTraceToLog(ELogVerbosity::Error);
```

## コードからログのVerbosityを変更する
このコードを追加するとコードからログのVerbosityを変更できます。
.iniファイルにログのVerbosity定義を追加したりコンソールコマンドの入力の手間を省略できます。
特定のシーンのみでVerbosityを変更したい場合に役立ちます。

```cpp:
	UE_SET_LOG_VERBOSITY(LogTemp, VeryVerbose);
```

## デバイスアウトプットを表示してログを見る
このコードを追加するとアウトプットデバイスウィンドウを表示します。
デスクトップPCで動作確認する際のログをリアルタイムで見る時に役立ちます。
特定のポイントからのみのログ出力を見たい時ありますよね。

```cpp:
#include "Misc/OutputDeviceConsole.h"

	GLogConsole->Show(true);
```

#Visual Studio
## Visual Studioからアタッチされるまで起動プロセスを待つ
アプリケーションの起動引数に`-WaitForDebugger`を追加してアプリ起動します。
Visual Studioからの起動ではなくインストール済みのアプリに対して起動時からアタッチできる。
インストール済みのアプリのPakマウント処理などをデバッグしたい時などに利用します。

【参考】: [[UE4] パッケージアプリの起動直後からデバッガをアタッチする](https://qiita.com/donbutsu17/items/77cdd27edad446b7195e)

## Visual Studioから起動プロセスにアタッチする
既に起動済みのアプリケーションに対して後からVSアタッチを実行できます。
[Debug]->[AttachToProcess]からアタッチしたプロセスを選択します。
インストール済みのアプリのデバッグ時などに役立ちます。
一度アタッチしたら[Debug]->[ReattachToProcess]で再アタッチが自動でできるのは楽です。
![2020-11-30_18h42_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/0b558508-9992-eee3-98dd-7531c4de9588.png)


## リモートデバッグポイントを作成する
起動引数を追加した場合にのみブレークするコードを追加できます。
アプリケーションの起動引数に`-PromptRemoteDebug`を追加して起動します。
エージングテスト中にブレークさせて途中からリモートデバッグしたい時などに役立ちます。
リモートデバッグポイントは以下のコードをデバッグしたいポイントに追加します。

```cpp:
	FPlatformMisc::PromptForRemoteDebugging(false);
```

ブレーク時には以下のウィンドウが表示されてその間にデバッガを接続します。
![2020-11-29_22h30_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/d8796ce7-0a2e-3d1e-fbcf-bb274d02223e.png)

## デバッガ接続時のみブレークするデバッグポイントを追加する
VSから起動時やプロセスアタッチ時にのみにブレークするようなデバッグポイントを作成できます。
パッケージやスタンドアローン動作にはブレークせずに動作を継続できます。
VSのF9ブレークポイントを使わないで任意に追加できるのでデバッグ時に役に立ちます。

```cpp:
	UE_DEBUG_BREAK();
```

## コンディションブレークを作成する
アドレスの内容が変わった時にデバッグポイントを作成できます。
値が上書きされたタイミングから、GCでオブジェクトが削除された時まで幅広いケースをキャッチします。
以下の例ではオブジェクトのアドレスを[Debug]->[NewBreakpoint]->[DataBreakpoint]から設定するだけです。
![2020-11-30_18h22_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/c24e2aa4-fd99-70d3-db94-c7baf77c3c72.png)

## Solutionを変更せずにビルドする
[UnrealVS](https://docs.unrealengine.com/ja/Programming/Development/VisualStudioSetup/UnrealVS/index.html)の機能でプロジェクトを右クリックからビルド構成とプラットフォームを指定してビルドが可能です。
ソースの変更を反映して実行ファイルから起動したい時なんかに役に立ちます。
ビルド構成, プラットフォームの切り替えに数秒程フリーズする時があるのでちょっとだけ短縮できます。
![2020-11-29_22h23_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/122b99e7-780d-e652-cbac-3927baf16a25.png)

## ThreadとStackの切り替え
Threadではブレークした時のThreadの動作状態を確認でき、
Stack FrameはCall Stackと同様に呼び出し履歴を確認できます。
UnrealInsightsやプロファイラーを使用しなくとも並列動作を確認できます。

・ブレークしているMainThread
![2020-11-30_23h45_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/fe66d0b6-bdc9-a899-fe91-4f72deaeab59.png)
・裏で動いているはずのPoolThread
![2020-11-30_23h46_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/dcb10b99-f8c0-87c1-6a23-5a284ebcaea6.png)


## デバッグ実行の遅延を解消する
VSからアプリ起動をしていると、バックグラウンドで様々な処理が走るため重くなりがちです。
デフォルトで有効になっているデバッグ時の処理を無効化すると幾分か軽くできます。
[Tools]->[Options]->[Debugging]->[General]で以下の設定を変更します。

・`Enable Diagnostic Tools while debugging`を無効にする
(デバッグ中に診断ツールを有効にする)

・`Show elapsed time PerfTip while debugging`を無効にする
(デバッグ中に経過時間の PerfTip を表示する)

![2020-11-29_21h37_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/058b459e-2192-cde5-7133-386e10aa62ff.png)

## ファイルオープン/デバッグ動作の遅延を改善する
UE4は膨大なコードを含むためIntelliSenseが非常に重いです。
IntelliSenseの機能を無効化するとメモリ、CPU動作を大幅に改善できます。
注意点としてIntelliSenseを無効にするとファイル検索機能などが制限されます。
[Tools]->[Options]->[Text Editor]->[C/C++]->[Advanced]で以下の設定を変更します。

・`Disable Database`を有効にする
([参照/ナビゲーション]の項目[データベースの無効化])
![2020-11-29_22h11_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/6fdc7877-0625-4700-ff60-42056f74f649.png)

## キーワード検索の効率化
[Entrian Source Search](http://entrian.com/source-search/)のキーワード検索はVS標準の検索に比べてかなり早いです。
デバッグをする時、コードを眺める時など、デバッグやコーディングで幅広く役に立ちます。
一度導入するとVS標準のファイル検索機能にはもう戻れません。

【参考】: [[UE4] Entrian Source SearchでUE４内部のソースコード検索を安価で容易に！](https://qiita.com/EGJ-Nori_Shinoyama/items/9385cf73b9a75966d803)

ファイル検索の際にエンジンソース外のファイルも含まれるので、検索の高速化と必要なファイルの抽出を限定するために以下のフィルタを使用しています。

**Additional file inclusion patterns for this index:**

```
*.ini
*.cpp
*.cs
*.h
*.inl
*.uplugin
```

**Additional file/directory exclusion patterns for this index:**

```
*\Content\*
*\Binaries\*
*\Saved\*
*.log
*.old
*.response
*\Intermediate\*
*\ThirdParty\*
```

## 任意検索の効率化
ファイル名とキーワードの両方で検索したいケースなどの検索ができます。
[Edit]->[Go to]から検索したいタイプを選択します。
[Find and Replace]や[Solution Explorer]よりは明らかに早い検索ができます。
![2020-11-30_15h23_52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/12733823-1d18-78e5-3b25-16ec1fe6a2fb.png)

アイコン選択で検索のフィルタを変更できます。
この[Go to All]ではファイル名やモジュール名などに関係無く全ての要素から検索します。
![2020-11-30_15h23_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/23480e8e-295f-d315-90e9-3d94feaebd6a.png)


#レベル
## 起動マップをオーバーライドする
アプリケーションの起動引数に`-defaultmap`を追加して、起動マップのパスを指定します。
Shipping以外で利用できるためTestビルドで検証する時にも利用できます。
特定のマップをデバッグしたい時にOpenコマンドで都度移動するのは地味に面倒なので短縮できます。

```cpp:
// マップのパスはSoftObjectPathで指定
-defaultMap=/Game/ThirdPersonCPP/Maps/DefaultMap.DefaultMap
```

## コンソールコマンドでサブレベルをロード/アンロードする
コンソールコマンドからレベルを指定してサブレベルをロード/アンロードします。
LoadStreamLevelを追加し忘れてパッケージを作成してしまったような時、
サブレベルの有無によって動作が変わる状況の検証を行う際に役立ちます。

```cpp:
// サブレベルはパッケージ名で指定
StreamLevelIn=/Game/ThirdPersonCPP/Maps/SubLevel
StreamLevelOut=/Game/ThirdPersonCPP/Maps/SubLevel
```

# ネットワーク
## コネクションタイムアウトの無効化
**・`-NoTimeouts`を起動引数に追加する**
マルチプレイ中にブレークでプログラムを止めているとセッションのタイムアウトを検出してしまいます。
アプリケーションの起動時に`-NoTimeouts`を追加することでタイムアウトを無効化できます。
ブレークで停止していても切断されないためネットワークのデバッグ時に役に立ちます。

# イテレーション
## Cookの効率化
**・CookerOption `-iterate`を追加する**
Cooked Directoryをクリーンせずに変更のあるアセットのみをクックできます。
デフォルトでは全てのクック済みアセットを削除するためクック時間を短縮できます。
リリース用パッケージング作成時には(これを使用しない)全クックをおすすめします。

**・CookerOption `-cooksinglepackage`を利用する**
全アセットクックではなく指定したアセット(とそれに付随する)アセットのみをクックできます。
【参考】: [[UE4] 1ファイル(と関連しているアセット)だけをクックする](https://qiita.com/EGJ-Takashi_Suzuki/items/ca9ab04c5b146e3ba5bd)

**・CookerOption `-outputdir`を利用する**
Cookしたアセット出力先を指定することができます。
本流とは別にCookファイルを保持しておきたい場合や、
Deterministic CookにおけるCookしたファイルの比較時にコピーの手間を省けます。

## Stagingの効率化
**・`-NoCleanStage`オプションを追加する**
Staging Directoryをクリーンせずに変更のある.pak/.ucas/.utocのみをコピーします。

## InstalledBuildの効率化
[InstalledBuild](https://docs.unrealengine.com/ja/Programming/Deployment/UsinganInstalledBuild/index.html)の作成は時間が掛かるので実行を最小にしてイテレーション効率を上げます。

**・特定のプラットフォームに限定してビルドする**
実行コマンドもしくはスクリプト中の定義で`-set:With[Platform]=false`を必要なプラットフォームに限定します。

**・特定のビルド構成に限定してビルドする**
実行コマンドもしくはスクリプト中の定義で`-set:GameConfigurations=[Config]`を必要な構成に限定します。

**・特定のプラットフォームに限定してビルドする**
実行コマンドもしくはスクリプト中の定義で`-set:WithDDC=false`と設定します。

**・`-clean`コマンドは付与しない**
ドキュメントにはInstalledBuild作成時のコマンドに`-clean`が定義されていますが、
InstalledBuild生成時はクリーン処理を削除することでイテレーション効率を上げることができます。

# デバッグ方法
## UATのデバッグ
UnrealAutomationTool(UAT)による動作をステップ実行で確認したい時に利用します。
UE4Editorとは別プロセスで動作するため、デバッグ時には少し設定を追加する必要があります。
【参考】: [[UE4] ビルドプロセス(UAT)をデバッグする方法](https://qiita.com/EGJ-Ken_Kuwano/items/56e5d5627997838b4350)

## UBTのデバッグ
UnrealBuildTool(UBT)による動作をステップ実行で確認したい時に利用します。
UE4Editorとは別プロセスで動作するため、デバッグ時には少し設定を追加する必要があります。
【参考】: [UnrealBuildToolをデバッグしてみる](https://qiita.com/EGJ-Takashi_Suzuki/items/a2a86e823d9000677c19)

## Commandletのデバッグ
Cook、Package、iostoreなどCommandlet処理の動作をステップ実行で確認したい時に利用します。
Startup Project=UE4, Development/Win64の構成でCommandletとOptionを引数として渡すだけです。

```:Cookコマンドの例
"G:\Projects\TP_425\TP_425.uproject" -run=cook -targetplatform=WindowsNoEditor -map=/Game/ThirdPersonCPP/Maps/Default
```

【参考】: [[UE4]クック処理にブレークを張りたい場合Commandletを使う] (https://qiita.com/EGJ-Yutaro_Sawada/items/e5430d6169b0a830811a)

## Nativizeのデバッグ
ネイティブ化を有効にするとネイティブ化したコードはIntermediate以下の以下のフォルダに格納されます。
C++と同様にVSからアプリを起動するとネイティブ化されたコードにもアタッチできます。

```
/[Project]/Intermediate/Plugins/NativizedAssets/Windows/Game/Source/NativizedAssets
```

## Testビルドのデバッグ
Testビルドで発生するバグの多くはDevelopmentでも再現可能な事がありますが、
非常に極々稀にTestビルドでしか発生しない様なバグに遭遇することもあります。
【参考】: [[UE4] ビルドコンフィギュレーション Test構成とは](https://qiita.com/donbutsu17/items/401c1fa1037a99e14b03)

## Shippingビルドのデバッグ
Shippingビルドで発生するバグの多くはDevelopmentでも再現可能な事がありますが、
Shippingでしか発生しないような場合はデバッグ機能を有効にして問題の切り分けからはじめます。
【参考】: [[UE4] Shippingのデバッグ](https://qiita.com/donbutsu17/items/76ea5c5531aa4da77f9d)

# 未分類
## BuildConfiguration.xmlのオーバーライド
`/Engine/Saved/UnrealBuildTool/Engine/Build/BuildConfiguration.xml`にあるファイルは、
`/Documents/Unreal Engine/UnrealBuildTool/BuildConfiguration.xml`に作成すると優先できます。
PGOやLTCGなどの設定を [BuildConfiguration.xml](https://docs.unrealengine.com/ja/Programming/BuildTools/UnrealBuildTool/BuildConfiguration/index.html)に定義する際、Engineファイルを書き変えが不要になります。
ローカルで検証する際には便利ですが、戻し忘れには注意して運用しましょう。

## ShaderDebug情報の出力
ConsoleVariables.iniにある以下をコメントアウトして有効にします。
その後にコンソールコマンド`RecompileShaders all`を実行するとSavedフォルダの下に作成されます。

`r.DumpShaderDebugInfo=1`
`r.Shaders.KeepDebugInfo=1`
`r.Shaders.Optimize=0`

## 起動開始直後にコンソールコマンドを実行する
アプリの起動直後から実行したいコンソールコマンドを登録することができます。
Debug, Development, Test, Shipping(PGOプロファイル時のみ)有効です。
stat xxx, gc.xxx, show xxx, r.xxx などは使うケースが多いと思います。

```cpp:
// 例:-execcmds="stat unit"
-execcmds="[Command1], [Command2], ..."
```

## フルクラッシュダンプの出力
アプリケーションがクラッシュする際に出力するMinidumpに詳細なデバッグ情報を追加します。
フルクラッシュダンプは多くの情報が得られるので、クラッシュの再現テスト時には設定すると役に立ちます。
起動引数に`-FullCrashDumpAlways`を追加してアプリケーション起動するとクラッシュ時に自動的に出力します。
`-FullCrashDump`を追加した場合はensureではフルクラッシュダンプを出力しない違いがあります。
出力するダンプファイルは`[Project_Root]/Saved/Crashes/`にあります。

![2020-11-30_23h12_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101019/0a7e4e6d-577a-9d2f-e01b-9aa2b555d1c1.png)

## Threadの制御
・`r.RHIThread.Enable` 
有効な場合、RHIThreadをRenderingThreadから独立して動作させます。
RHIThreadがサポートされるプラットフォームでのみ動作が可能です。

・`s.AsyncLoadingThreadEnabled` 
有効な場合、AsyncLoadingThreadをMainThreadから独立して動作させます。